0

本题询问一个有 100 个状态且每个状态有 100 个事件的有限状态机,然后对使用if-elseswitch语句或函数指针来实现状态机进行简要比较。

我的问题是:如果使用函数指针,如何正确设置函数指针?使用if-elseorswitch语句(在这种情况下,函数指针会更像是一种混合解决方案)?还是有另一种常见的方法?

4

3 回答 3

2

我希望每个状态都由一个函数表示,并且所有状态都可以“了解”彼此。

因此,设置可以是直接的:

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意味着“不要切换”。

于 2012-12-13T16:30:30.403 回答
1
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" },

如果一个函数处理程序可以服务于多个状态,这很方便。

于 2012-12-13T16:43:23.473 回答
1

您可以执行以下操作:

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 指针。此外,您可以修改函数指针以获取输入参数。

于 2012-12-13T16:43:46.420 回答