本题询问一个有 100 个状态且每个状态有 100 个事件的有限状态机,然后对使用if-else
、switch
语句或函数指针来实现状态机进行简要比较。
我的问题是:如果使用函数指针,如何正确设置函数指针?使用if-else
orswitch
语句(在这种情况下,函数指针会更像是一种混合解决方案)?还是有另一种常见的方法?
本题询问一个有 100 个状态且每个状态有 100 个事件的有限状态机,然后对使用if-else
、switch
语句或函数指针来实现状态机进行简要比较。
我的问题是:如果使用函数指针,如何正确设置函数指针?使用if-else
orswitch
语句(在这种情况下,函数指针会更像是一种混合解决方案)?还是有另一种常见的方法?
我希望每个状态都由一个函数表示,并且所有状态都可以“了解”彼此。
因此,设置可以是直接的:
void set_state(void (*state)(void))
{
the_current_state = state;
}
void state_idle(void)
{
printf("oh, hai, boring to be in the idle state, let's switch\n");
set_state(state_busy);
}
这假定当前状态由全局函数指针 ( the_current_state
) 建模。
您当然也可以让每个状态返回新状态,或者可能NULL
意味着“不要切换”。
struct state_fn {
void (*handler)(void);
};
static int state;
static struct state_fn[MAX_STATE] = {
{ .handler = handler_state_0, },
{ .handler = handler_state_1, },
{ .handler = handler_state_2, },
};
然后调用 state_fn[state]->handler();
您可以选择从结构中添加参数。像这样:
struct state_fn {
void (*handler)(void *data);
void *data;
}
然后调用 state_fn[state]->handler(state_fn[state]->data);
{ .handler = handler_state_0, .data = "blabla" },
如果一个函数处理程序可以服务于多个状态,这很方便。
您可以执行以下操作:
typedef int (*current_state) (void);
typedef int (*nextnew_state) (void);
struct FuncPointerState
{
current_state curr_state;
nextnew_state next_state;
};
/*init_state is the initial function state*/
struct FuncPointerState FpState = {init_state, NULL};
int iRet = 0;
while(1)
{
iRet = FpState.curr_state();
if(iRet<= 0 )
{
return iRet;
}
if(NULL==FpState.next_state)
{
/* State Machine finished it's job */
break;
}
FpState.curr_state = FpState.next_state;
}
每个状态函数都应该填充 next_state 指针。此外,您可以修改函数指针以获取输入参数。