関数ジャンプテーブルサンプル

Cでよく使われる(?)関数ポインタを用いたステートマシンのサンプルです。

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