[解決済み] ステートマシンの典型的な実装パターンはありますか?
2022-07-31 04:17:11
質問
の簡単なステートマシンを実装する必要があります。
C
.
標準のswitch文が一番いいのでしょうか?
現在の状態(state)と、遷移のトリガーを用意しています。
switch(state)
{
case STATE_1:
state = DoState1(transition);
break;
case STATE_2:
state = DoState2(transition);
break;
}
...
DoState2(int transition)
{
// Do State Work
...
if(transition == FROM_STATE_2) {
// New state when doing STATE 2 -> STATE 2
}
if(transition == FROM_STATE_1) {
// New State when moving STATE 1 -> STATE 2
}
return new_state;
}
もっといい方法はないか 単純なステートマシンの場合
EDIT C++の場合、Boostの 状態図 ライブラリがいいかもしれません。 しかし、それは ではない Cの使用例に集中しましょう。
どのように解決するのですか?
私は、ほとんどのステートマシンでテーブル駆動のアプローチを使用することを好みます。
typedef enum { STATE_INITIAL, STATE_FOO, STATE_BAR, NUM_STATES } state_t;
typedef struct instance_data instance_data_t;
typedef state_t state_func_t( instance_data_t *data );
state_t do_state_initial( instance_data_t *data );
state_t do_state_foo( instance_data_t *data );
state_t do_state_bar( instance_data_t *data );
state_func_t* const state_table[ NUM_STATES ] = {
do_state_initial, do_state_foo, do_state_bar
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
return state_table[ cur_state ]( data );
};
int main( void ) {
state_t cur_state = STATE_INITIAL;
instance_data_t data;
while ( 1 ) {
cur_state = run_state( cur_state, &data );
// do other program logic, run other state machines, etc
}
}
もちろん、これを拡張して、複数のステートマシンをサポートすることなども可能です。トランジションアクションも対応可能です。
typedef void transition_func_t( instance_data_t *data );
void do_initial_to_foo( instance_data_t *data );
void do_foo_to_bar( instance_data_t *data );
void do_bar_to_initial( instance_data_t *data );
void do_bar_to_foo( instance_data_t *data );
void do_bar_to_bar( instance_data_t *data );
transition_func_t * const transition_table[ NUM_STATES ][ NUM_STATES ] = {
{ NULL, do_initial_to_foo, NULL },
{ NULL, NULL, do_foo_to_bar },
{ do_bar_to_initial, do_bar_to_foo, do_bar_to_bar }
};
state_t run_state( state_t cur_state, instance_data_t *data ) {
state_t new_state = state_table[ cur_state ]( data );
transition_func_t *transition =
transition_table[ cur_state ][ new_state ];
if ( transition ) {
transition( data );
}
return new_state;
};
テーブル駆動のアプローチは、メンテナンスと拡張が容易で、状態図にマッピングするのも簡単です。
関連
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
[解決済み] Code::Blocks アプリケーションをコンパイルできない
-
[解決済み] Xcode - 警告。C99 では関数の暗黙の宣言は無効です。
-
[解決済み] ⑭と⑯は何のためにあるのですか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] 静的クラスとシングルトンパターンの違い?
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み】C++ シングルトンデザインパターン
-
[解決済み】C++でファクトリーメソッドパターンを正しく実装する方法
-
[解決済み] switch文はなぜブレークが必要な設計になっているのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
赤線の位置は必ずしも間違っていない:式は変更可能なlvalueでなければならないエラーは、この文とは別の場所に存在する可能性があります。
-
警告:代入がキャストなしで整数からポインタを作成する場合の修正方法に関する警告
-
[解決済み] Code::Blocks アプリケーションをコンパイルできない
-
[解決済み] Xcode - 警告。C99 では関数の暗黙の宣言は無効です。
-
[解決済み] ⑭と⑯は何のためにあるのですか?
-
[解決済み] while ( !feof (file) ) 」は、なぜいつも間違っているのですか?
-
[解決済み] なぜsizeof(x++)はxをインクリメントしないのですか?
-
[解決済み] アセンブリがCより速いのはどんなとき?[クローズド]
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み] C言語で "unsigned long "をprintfする方法は?