0

この質問では、100個の状態と100個のイベントを持つ各状態を持つ有限状態マシンについて質問し、次に、、ステートメント、または関数ポインターを使用して状態マシンを実装することを簡単に比較しif-elseますswitch

私の質問は、関数ポインタを使用する場合、関数ポインタはどのように適切に設定されるのでしょうか。if-elseまたはステートメントを使用するとswitch(この場合、関数ポインターはよりハイブリッドなソリューションになります)?または、これが一般的に行われる別の方法はありますか?

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" },

これは、1 つの関数ハンドラーが複数の状態を処理できる場合に便利です。

于 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 に答える