C 语言中的状态机实现



我一直在尝试用 C 语言实现状态机,但我不是 确定我的实现是否合适。我尝试以伪对象方式实现状态图。所以我在StateMachine.h头文件中声明了StateMachine"class"的公共接口:

typedef enum{
STATE_01,
STATE_02,
STATE_03,
STATE_04
}state_e;
typedef enum{
NO_EVENT,
EVENT_01,
EVENT_02,
EVENT_03,
EVENT_04,
EVENT_05,
EVENT_06,
EVENT_07
}event_e;
// state machine instance
typedef struct{
state_e currState;
}StateMachine;
extern void InitState(StateMachine*);
extern void ProcSTATE_01(StateMachine*, event_e);
extern void ProcSTATE_02(StateMachine*, event_e);
extern void ProcSTATE_03(StateMachine*, event_e);
extern void ProcSTATE_04(StateMachine*, event_e);
extern void ProcEvent(StateMachine*, event_e);

StateMachine 对象 "methods" 的实现在 StateMachine.c 模块中:

void InitState(StateMachine *sm)
{
sm->currState = STATE_01;
}

void ProcSTATE_01(StateMachine *sm, event_e event)
{
if(event == EVENT_01){
sm->currState = STATE_02;
}
}
void ProcSTATE_02(StateMachine *sm, event_e event)
{
// ...
}
void ProcSTATE_03(StateMachine *sm, event_e event)
{
// ...
}
void ProcSTATE_04(StateMachine *sm, event_e event)
{
// ...
}

void ProcEvent(StateMachine *sm, event_e event)
{
switch(sm->currState){
case STATE_01:
ProcSTATE_01(sm, event);
break;
case STATE_02:
ProcSTATE_02(sm, event);
break;
case STATE_03:
ProcSTATE_03(sm, event);
break;
case STATE_04:
ProcSTATE_04(sm, event);
break;
}
}

状态机对象的用法如下:

int main(int argc, char** argv) {
StateMachine app;
ProcEvent(&app, EVENT_01);
return 0;
}

我想问任何更有经验的人,他是否可以看到与此实现相关的任何潜在问题。感谢您的任何评论。

您需要考虑事件的来源。 它们是仅由状态转换处理程序本身生成,还是外生的。 如果它们是外生的,那么您可能需要在处理程序外部有一个事件循环,该循环从队列中提取事件并将它们注入到适当的处理程序(这可能会将另一个事件排队到队列以供以后处理(。 此外,您可能希望将状态事件处理程序函数存储在数组中(根据状态号编制索引(,以便能够以编程方式调用它们(而不必具有巨大的 switch 语句(。

没有"正确"的方法来实现状态机(如Doug提到的状态表aproach(,但是有一些代码可以让您直接了解哪些易于使用,哪些不可用。 Miro Samek 有一本关于在 c/c++ 中使用 hirarchical 状态机的书。在那里,他将不同的风格与他开发的状态机风格进行了比较。我必须说,他的风格对我来说是最合理和可读的。 本书的一部分也可在 state-machine.com 在线获得。 你的状态机骨架实际上与 Miros aproach 的状态机部分非常相似,他的 aproach 还增加了一个多毛转换的可能性,每个状态机的队列,一个系统滴答机制,事件回收,一个零事件复制策略等等。如果你看看他的网站,你会发现你的aproach是一个很好的,可以用很多很多方式扩展。

最新更新