Cでよく使われる(?)関数ポインタを用いたステートマシンのサンプルです。
Cでよく使われる(?)関数ポインタを用いたステートマシンのサンプルです。
#include <stdio.h> // 状態番号 static unsigned char sucState; // 投入金額 static int siCharge; // Suica残高(仮) static int siSuica = 2000; // 状態 enum E_STATE{ IDLE = 0, POOR, SELECTED, SUFFICE, STATE_MAX }; // イベント enum E_EVENT{ INJECT = 0, CHANGE, SUICA, JUICE_SELECT, EVENT_MAX }; // ジュースの値段 const int JUICE_PRICE = 120; // const char MESSAGE[EVENT_MAX][20]= { "100円投入", "おつり返却", "Suicaタッチ", "ジュース選択" }; // 関数ポインタの型宣言 typedef int (*JumpTable)( int* ); // ダミー関数宣言 int Dummy( int * ); // 関数宣言 int St00Ev00( int* ); int St00Ev02( int* ); int St00Ev03( int* ); int St01Ev00( int* ); int St01Ev01( int* ); int St02Ev02( int* ); int St03Ev00( int* ); int St03Ev03( int* ); // ジャンプテーブルの登録 const JumpTable fpVendingMachine[STATE_MAX][EVENT_MAX] = { // 100円投入 おつり返却 Suicaタッチ ジュース選択 { &St00Ev00, &Dummy, &St00Ev02, &St00Ev03 }, // 初期状態 { &St01Ev00, &St01Ev01, &Dummy, &Dummy }, // 金額不足状態 { &Dummy, &Dummy, &St02Ev02, &Dummy }, // ジュース選択状態 { &St03Ev00, &St01Ev01, &Dummy, &St03Ev03 }, // 購入可能状態 }; // ダミー関数 int Dummy( int *arg ) { return( sucState ); } int St00Ev00( int *arg ) { *arg += 100; return( POOR ); } int St00Ev02( int *arg ) { printf("Suica残高:%d円\n",*arg); return( sucState ); } int St00Ev03( int *arg ) { printf("ジュース選択\n"); return( SELECTED ); } int St01Ev00( int *arg ) { int ret = sucState; St00Ev00( arg ); if ( siCharge >= JUICE_PRICE ) { ret = SUFFICE; } return( ret ); } int St01Ev01( int *arg ) { printf("%d円返却\n",*arg); *arg = 0; return( IDLE ); } int St02Ev02( int *arg ) { int ret = IDLE; if ( *arg >= JUICE_PRICE ) { ret = St03Ev03( arg ); } return( ret ); } int St03Ev00( int *arg ) { *arg += 100; return( sucState ); } int St03Ev03( int *arg ) { int ret = IDLE; printf("ジュース購入!\n"); *arg -= JUICE_PRICE; if ( fpVendingMachine[sucState][CHANGE] != Dummy ) { if ( *arg < JUICE_PRICE ) { ret = fpVendingMachine[sucState][CHANGE](arg); } else { ret = sucState; } } return( ret ); } int main( int argc, char* argv[] ) { int i, c, event, *p; // メインループ while( 1 ){ // コマンド表示 for( i = 0; i < EVENT_MAX; i++ ){ if ( fpVendingMachine[sucState][i] != Dummy ) { printf("%d:%s\n", i,MESSAGE[i] ); } } puts(""); // コマンド入力 scanf("%d",&c); fflush( stdin ); event = ( c >= 0 && c <= EVENT_MAX )? c: EVENT_MAX; if ( event >= EVENT_MAX ) { puts("error"); continue; } if ( event == SUICA ) { p = &siSuica; } else { p = &siCharge; } // 関数コール sucState = fpVendingMachine[sucState][event](p); } return( 0 ); }