c++状态机的使用
创始人
2024-03-25 04:30:16
0

什么是状态机

状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。英文名字叫State Machine ,不是指一台实际机器,一般就是指一张状态转换图。全称是有限状态自动机,自动两个字包含重要含义。给定一个状态机,同时给定它的当前状态以及输入,那么输出状态时可以明确的运算出来的,当输入条件时,能输出下一个状态。

现实事物是有不同状态,例如一个LED等,就有 亮 和 灭两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如LED灯的状态就是两个亮和 灭。

在这里插入图片描述

为什么用状态机

状态机解决的问题就是当某种模型的状态变更比较比较复杂,且状态比较多,那么我们有必要将这些状态变化的逻辑抽象出来,做成一个可以统一调用的算法,这样封装出来的代码就比较好维护,同时可读性也很强。

状态机在实际工作开发中很有用,应用也非常广泛。一个健壮的状态机可以让你的程序,不论发生何种突发事件都不会突然进入一个不可预知的程序分支,可以很清晰的表达整个状态的流转。

在GUI应用程序、Web应用程序等事件驱动型的应用程序,采用状态机的思路来完成程序设计,可以简化设计流程,使程序的可读性、可维护性都得到增加。

 使用状态机有哪些好处?
1. 当一个程序有多个状态时,规范了状态机的状态转换,避免了一些引入一些复杂的判断逻辑。
2. 规范了程序在不同状态下所能提供的能力。
3. 在能力上可以进行横向扩展,提供新的状态来完善现有逻辑。

简单状态机的实现

使用switch跳转即可实现一种简单的状态机。如果逻辑不是很复杂,使用switch语句也能达到实现目的。举例如下:

enum state{nullState_,firstState_,secondState_,thirdState_,quitState_,};struct param_t{int param1;int param2;
// ......};int nullStateProc(param_t& param){return firstState_;
}int firstStateProc(param_t& param){return secondState_;
}int secondStateProc(param_t& param){return secondState_;
}int thirdStateProc(param_t& param){return secondState_;
}int quitEvent(){return nullState_;
}int stateMachine(state& state_, param_t& param){switch (state_){case nullState_:state_ = static_cast(nullStateProc(param));break;case firstState_:state_ = static_cast(firstStateProc(param));break;case secondState_:state_ = static_cast(secondStateProc(param));break;case thirdState_:state_ = static_cast(thirdStateProc(param));break;case quitState_:quitEvent();return 0;}return 1;}void start()
{state state_ = nullState_;param_t param{};while (true){auto stateResult = stateMachine(state_, param);if (!stateResult){return;}}
}

另一种简单实现

如果需要管理的状态和事件比较多,需要逻辑清晰和便于维护,使用简单的switch可能无法满足需求。这里介绍一种简单的实现,消除庞大的条件分支语句,从配置表容易看出各个状态的转换图。

/*  statemachine.h*/#ifndef _STATEMACHINE_H_
#define _STATEMACHINE_H_#include enum EventActionResult {EventFailed, EventProcessedOK
};template
class State {
public:std::string inputEvent;State *nextState;EventActionResult (T::*action)(const std::string &event, P *param);State *errorState;
};template
class StateMachine {
private:State *init;State *current;T *target;public:StateMachine() {}void Init(T *_target, State *initialState) {init = current = initialState;target = _target;}void Reset() {current = init;}void ProcessEvent(const std::string &event, P *param) {for (State *p = this->current; p->nextState != NULL; p++) {if (p->inputEvent == event) {if (p->action != NULL) {if (EventFailed == (this->target->*(p->action))(event, param)) {if (p->errorState != NULL) {//Only if there's an errorstate defined. Otherwise, just do nothingthis->current = p->errorState;}return;}}this->current = p->nextState;return;}}//Event not found. Do nothingreturn;}
};

以下是使用举例:

class MyStateMachine {
public:struct param_t {int param;int param1;int param2;};StateMachine stMachine;EventActionResult HandleEvent1(const std::string &e, param_t *param);EventActionResult HandleEvent2(const std::string &e, param_t *param);EventActionResult HandleEventA(const std::string &e, param_t *param);EventActionResult HandleEventB(const std::string &e, param_t *param);EventActionResult HandleThree(const std::string &e, param_t *param);void HandleEvent(const std::string &e, param_t *param);void Init();void Start();
};
#include "statemachine.h"
#include 
#include 
#include typedef State STATE;extern STATE Idle[];
extern STATE One[];
extern STATE Two[];STATE Idle[] ={//EVENT,NEXT,  ACTION,   ERRORSTATE (where to land if there's an error){"event1", One, &MyStateMachine::HandleEvent1, Idle},{"event2", Two, &MyStateMachine::HandleEvent2, Idle},{"", NULL, NULL, NULL}, //End of table};STATE One[] ={{"eventA", Idle, &MyStateMachine::HandleEventA, Idle},{"eventB", Idle, &MyStateMachine::HandleEventB, Idle},{"", NULL, NULL, NULL},};STATE Two[] ={{"eventC", Idle, NULL, NULL},{"", NULL,  NULL, NULL},};EventActionResult MyStateMachine::HandleEvent1(const std::string &e, param_t *param) {std::cout << "HandleEvent1,param:" << param->param << std::endl;return EventProcessedOK;
}EventActionResult MyStateMachine::HandleEvent2(const std::string &e, param_t *param) {std::cout << "HandleEvent2,param:" << param->param << std::endl;return EventProcessedOK;
}EventActionResult MyStateMachine::HandleEventA(const std::string &e, param_t *param) {std::cout << "HandleEventA,param:" << param->param << std::endl;return EventProcessedOK;
}EventActionResult MyStateMachine::HandleEventB(const std::string &e, param_t *param) {std::cout << "HandleEventB,param:" << param->param << std::endl;return EventProcessedOK;
}EventActionResult MyStateMachine::HandleThree(const std::string &e, param_t *param) {std::cout << "HandleThree" << std::endl;return EventProcessedOK;
}void MyStateMachine::HandleEvent(const std::string &e, param_t *param) {stMachine.ProcessEvent(e, param);
}void MyStateMachine::Init() {stMachine.Init(this, Idle);
}void MyStateMachine::Start() {while (1) {char c[255];// 模拟输入eventstd::cin.getline(c,255);std::string event{c};MyStateMachine::param_t param;param.param = 1;this->HandleEvent(event, ¶m);}
}

引用

什么是状态机?_pingxiaozhao的博客-CSDN博客_状态机的概念

为Linux应用构造有限状态机_wowocpp的博客-CSDN博客_linux 状态机

有限状态机详解(转载)_白小狮的博客-CSDN博客_有限状态机和无限状态机

Linux进程是如何创建出来的?

为Linux操作系统应用构造有限状态机方法-红联Linux系统门户

一文详解 Android状态机StateMachine 使用方式及实现原理_bjxiaxueliang的博客-CSDN博客_statemachine

c++写状态机_zhi_cary的博客-CSDN博客_c++ 状态机

C++有限状态机的实现_Valreaper的博客-CSDN博客_c++ 状态机

github经典C++状态机(fsm)源代码剖析_star-keke的博客-CSDN博客

用C++来实现有限状态机(附代码)_李肖遥的博客-CSDN博客

TinyFSM 介绍_百思可乐的博客-CSDN博客

C++状态机框架实现 - 灰信网(软件开发博客聚合)

状态模式(state)C++实现_shu_chang1993的博客-CSDN博客_c++state

c++写状态机_zhi_cary的博客-CSDN博客_c++ 状态机

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...