C言語には関数のアドレスを管理するための変数「関数ポインタ」があります。
今回はC言語の関数ポインターでディシジョンテーブル(決定表)を作って、IF文を減らしてソースを簡易にしてみます。
C言語の関数ポインタ
C言語には関数のアドレスを管理する「関数ポインタ」という変数を作ることができます。
関数ポインタの宣言は
関数の戻り値型 ( 変数名 )( 引数・・・);
で宣言します。
関数の戻り値型 ( 変数名 )( 引数・・・);
で宣言します。
実際に書くと
int ( *po )( int, char, long ) ;
のようになります。
関数ポインタでディシジョンテーブル(決定表)を作る
では実際に関数ポインタでディシジョンテーブル(決定表)を作ってみます。
でもその前に「関数ポインタのディシジョンテーブル(決定表)」を使わずに書くとどうなるかやってみます。
#include <stdio.h> #include <string.h> //プロトタイプ宣言 void dog( void ) ; void cat( void ) ; void monkey( void ) ; //メイン関数 int main() { char s[ 20 ] ; printf( "実行する関数を指定してください dog,cat,monkey >" ) ; gets( s ) ; if( strcmp( "dog", s ) == 0 ){ dog(); } else if( strcmp( "cat", s ) == 0 ){ cat(); } else if( strcmp( "monkey", s ) == 0 ){ monkey(); } else { printf("%sは決定表の中にはありません。\n", s ) ; } return 0 ; } //イヌの鳴き声 void dog() { printf("bow wow\n"); } //ネコの鳴き声 void cat() { printf("meow\n"); } //サルの鳴き声 void monkey() { printf("screech\n"); }
となります。
これを「関数ポインターのディシジョンテーブル(決定表)」を使うと
#include <stdio.h> #include <string.h> //プロトタイプ宣言 void dog( void ) ; void cat( void ) ; void monkey( void ) ; //決定表(ディシジョンテーブル)定義構造体 typedef struct{ char label[ 20 ] ; void ( *po )() ; /*関数ポインタ宣言*/ } DECISION_TABLE ; //メイン関数 int main() { char s[ 20 ] ; DECISION_TABLE dt[ 3 ] ={ { "dog", dog } ,{ "cat", cat } ,{ "monkey", monkey } } ; printf( "実行する関数を指定してください dog,cat,monkey >" ) ; gets( s ) ; for( int i = 0 ; i < sizeof( dt ) / sizeof( DECISION_TABLE ) ; i++ ){ if( strcmp( dt[ i ].label, s ) == 0 ){ dt[ i ].po(); return 0; } } printf("%sは決定表の中にはありません。\n", s ) ; return 0 ; } //イヌの鳴き声 void dog() { printf("bow wow\n"); } //ネコの鳴き声 void cat() { printf("meow\n"); } //サルの鳴き声 void monkey() { printf("screech\n"); }
となり「if文」が随分と少なくなりました。
また、動物の鳴き声関数が増えててもディシジョンテーブル(決定表)を追加するだけでif文を追加する必要はなく、メインループの変更はなくなりました。
まとめ
C言語の関数ポインタを使ってディシジョンテーブル(決定表)を作って処理を分岐させると、IF文を減らすことができ、処理の追加などでもディシジョンテーブル(決定表)を修正するだけで済むようになります。
これで随分メンテナンスがしやすいソースになりました。