プロが教える店舗&オフィスのセキュリティ対策術

C言語にて開発を行っています。
今回、テキストファイルに記述された関数名および引数を読み取り、プログラム側でこれを実行する処理を実装しようと考えています。
その際、テキストから読み込んだ文字列によって処理を振り分けることを省略したいと思っていますが方法が分からず困っています。

以下が読み取る対象のテキストファイルの例です。

@function_A;arg1;arg2
@function_B;arg1;arg2
・・・

このとき、テキストファイルから読み取った文字列に応じた関数を実行する、というところまでは実装できています。
(読み取った文字列がfunction_Aであれば、同名の関数を実行します)
現在の実装は、以下のようなイメージです。

command = "読み取った文字列(@function_Aなど)";
if(command == "@function_A"){ function_A(arg1, arg2);}
else if(command == "@function_B"){ function_B(arg1, arg2);}
・・・
しかし、この実装では関数が増えるに従って
if(command == "function_X"){...}をどんどん追記していく必要があります。
今後関数の数が膨大になっていく予定なので、これを追記せずに読み込んだ文字列と同名の関数を実行できるようにしたいと思っています。
以下の様なイメージです。

function_A.cというファイルに関数function_A(arg1, arg2)を実装します。
同様にして、 function_B.cに関数function_B(arg1, arg2)を実装します。
main()内にて、
char command[] = "読み取った文字列(function_Aなど)";
command(arg1, arg2);
とすることによって、function_A()関数を実行できるようにすることが目的です。

もちろん、この場合のcommandはchar型ですから、上記のような記法が不可能なことは分かっていますが、似たようなことを実装したいと思っています。

どのようにすれば実装できるのでしょうか。
今後、関数の数だけfunction_A.cのようなファイルが増え、最終的に200近くになる予定ですし、
if(command == "@function_A"){ function_A(arg1, arg2);}
else if(command == "@function_B"){ function_B(arg1, arg2);}
・・・
の記述忘れによる動作不良を防ぐためにもこれを実装したいと思います。

A 回答 (7件)

GNU が嫌いじゃないなら gperf なんて手もあることはある.

    • good
    • 0

Cの規格上は既に回答に出てる通りの方法しかないです。



プラットホームに依存してよければ、
WindowsだとGetProcAddress, linuxや一部unix系だとdlsymを使う手もあります。
    • good
    • 0

ANo.1です。


ハッシュテーブルへの登録は関数の数だけ書く必要があります。
set_table(table, "@function_A", function_A);
set_table(table, "@function_B", function_B);
...
のような感じですね。
これも省略したければCソースを自動生成するスクリプトなど作るしかないでしょう。

実際に文字列から関数を取得する部分はハッシュテーブルを使うならif羅列とは全然違います。
ハッシュテーブルは文字列からハッシュ値を計算して、このハッシュ値の位置に文字列と値(関数ポインタ)を格納します。検索する際もハッシュ値を計算してハッシュ値の位置の文字列が探しているものか確認して値を取り出します。
従って、検索時は(ほとんどの場合)文字列の比較は一回だけで済みます。
エントリが200もあるなら実行時の速度も全然早くなるのでハッシュテーブルを使うべきでしょう。
    • good
    • 0

> @function_A;arg1;arg2


> @function_B;arg1;arg2

から、

funciton_A(arg1, arg2);
function_B(arg1, arg2);

という、Cのソースを生成して、それを、コンパイル、リンクして実行する。

というのは?
    • good
    • 0

念の為に確認しますが


> command = "読み取った文字列(@function_Aなど)";
> if(command == "@function_A"){ function_A(arg1, arg2);}
本当に = で代入、 == で比較、とかはやってないですね?

struct FunctionTable{
char name[STRMAX] ;
void (*func)();
} table[] = {
{ "@function_A", function_A },
{ "@function_B", function_B }
} ;

のように、文字列と関数へのポインタののテーブルを作って
for(i=0; ...
...
if( strcmp( command, tablle[i].name ) == 0 ) {
table[i].func(arg1,arg2);
}

みたいに、文字列比較→該当する関数を実行 というのが定番でしょう。

他の言語、特にスクリプト言語には
command="function_A(arg1.arg2)" ;
eval( command ) ;
みたいに書いて、文字列をそのまま命令として実行できるものがあります。
しかし、C言語にはこのような仕組みは無いので、地道な方法しかありません。


記述漏れを防ぐには、自動化すればよいでしょう。
C言語のソースから、テーブルを自動で作るようなプログラムを準備し,本体をコンパイルする前に実行します。
cretateTable funcitons.c → functions.cを解析して、table.c が作成される
というような感じで。


他に、共有ライブラリを使う方法があります。
f = 共有ライブラリからシンボルを探す関数( commad ) ;
f(arg1,arg2) ;
という感じです。
WindowsならDLLにfunction_A..等の実体→ LoadLibrary→GetProcAddress でしょうか。
    • good
    • 0

規格上は #1 の方法しかないと思う.



OS やコンパイラなどの情報があればほかの方法も考え得る.
    • good
    • 0

ハッシュテーブルか何かを使って文字列と関数ポインタの対応表を実装する。


プログラムの起動時に文字列と関数ポインタの対応を上記対応表に登録する処理を入れる。
実行時は文字列で対応表を引いて関数ポインタを得て実行する。
関数は全て同じプロトタイプになるようにしておく必要があります。

C++だと対応表はhash_mapとかのライブラリクラスを使って良いですがCだと自前で実装ですかね。
あと対応表への登録は明示的に実行するしかないですね。

この回答への補足

文字列と関数ポインタの対応表を作成するということは、結局のところやっていることは
if(command == "@function_A"){ function_A(arg1, arg2);}
else if(command == "@function_B"){ function_B(arg1, arg2);}
に相当するものを関数の追加に応じて記述していくことになると思うのですが、この認識は合っていますでしょうか?

補足日時:2013/06/25 11:04
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!