0

stdin から読み取るプログラムを書きたい:scanf("%s %s", foo, args);次に、関数 foo (前にプログラムで定義されたもの) を引数付きで実行する: foo(args);C でこれを行う方法がわかりません。以前はシェルでこれを簡単に実行できましたが、Cでは難しいようです

4

2 に答える 2

6

一般化され、同時にクロスプラットフォーム/標準であるこの問題の解決策はありません。

非標準の拡張機能に依存しない非一般的なソリューション: 名前と関数ポインターのペアを配列に格納し、検索を実行し、ポインターによって関数を呼び出します。例えば:

struct namedfunc {
    const char *name;
    void (*fptr)(void);
} fvect[3] = {
    { "foo", foo_impl },
    { "bar", bar_impl },
    { "baz", baz_impl }
};

char buf[0x100];
fgets(buf, sizeof buf, stdin);
char *p = strchr(buf, '\n');
if (p != NULL)
    *p = 0;

for (size_t i = 0; i < sizeof fvect / sizeof fvect[0]; i++) {
    if (strcmp(buf, fvect[i].name) == 0) {
        fvect[i].fptr();
        break;
    }
}

利用可能な動的読み込みに依存するより一般的な解決策: 次のようにdlopen()APIを使用します。

void *hndl = dlopen(RTLD_SELF, RTLD_LAZY); // try NULL if RTLD_SELF doesn't work
void (*fptr)(void) = dlsym(hndl, buf);
if (fptr != NULL)
    fptr();

dlclose(hndl);
于 2013-09-30T16:07:17.440 に答える
2

デバッグが難しく、非常に壊れやすい別のソリューションには、デバッグ シンボル (またはマップ ファイル) を使用してコンパイルし、それらを解析して関数を動的に呼び出すことが含まれます。それはクレイジーです。

当然のことですが、プログラム内のすべての関数をこの方法で呼び出し可能にしたいですか? 含むmain? おそらくそうではありません。それでは、この方法で呼び出すことができる一連の関数を特定し、関数名と関数ポインターを含む構造体の配列を作成します。入力時に関数名が表示されたら、その関数の配列をスキャンし、関数ポインターを見つけて呼び出します。プロトタイプが異なる場合は、関数が期待するパラメーターの種類を記述する別のメンバーを追加します。(編集:上記の回答は同じことを示唆しており、詳細を提供しています)

于 2013-09-30T16:12:22.607 に答える