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 );}