3

数千以上の固有のケースを含むswitchcaseステートメントがあります。ユーザーが各ケースをケース番号で覚えるのは困難です。したがって、私はケースごとに一意の文字列を使用し、それをハッシュして、指定された文字列の選択'sel'を取得しています。

   % Example c code
   sel =hashfunction(string)
   switch (sel) {
     case 0:
          func0(); 

     case 1:
          func1();
     ......
     ......
    case 10000:
         func10000();
   }

ただし、このコードは1つのファイルに収める必要があるため非常に大きくなり、たとえば100行のコーディングガイドラインにも違反します。ケースと関数呼び出しの一意のマッピングがあるため、ポインターを使用してforループ内で関数を呼び出して呼び出すことができると思います。これは、スイッチケースよりも非常にコンパクトになります。これを達成するための助けは大歓迎です。

4

2 に答える 2

5

各関数の型と命名規則が同じであり、POSIX を使用している場合は、動的リンク ローダーを使用して関数の名前を計算し、それを動的に呼び出して実行できます。

例:

#include <stdio.h>
#include <dlfcn.h>

typedef void (*funcptr)(void);

void func1(void) {
    printf("in func1");
}

void func2(void) {
    printf("in func2");
}

void call_some_func(int sel) { /* where sel is the return val of hashfunction */
    void* dl = dlopen(NULL, RTLD_LAZY);
    if (dl == NULL) { /* handle error */ }

    char sym_name[64];
    snprintf(sym_name, sizeof sym_name, "func%d", sel);

    void* sym = dlsym(dl, sym_name);
    if (sym == NULL) { /* handle error */ }

    ((funcptr)sym)();
}

ここで、呼び出しはなどcall_some_func(1)を実行します。func1()

これを機能させるには、dlライブラリをリンクし、実行可能ファイルのシンボルをエクスポートする必要があります。GCC では:

gcc source.c -Wall -ldl -rdynamic

でコンパイルする-rdynamicと、実行可能ファイルのサイズが大きくなることに注意してください。

于 2012-12-28T18:58:10.637 に答える
3

すべてのケースが単純な関数呼び出しである場合 (func1、func2、func3 などと呼ばれないことを願っています)、1 つの長い switch ステートメントがこの問題を解決する最もクリーンで簡単な方法であると私は信じています。私の本では、コーディング標準は、他のことをする価値があるほど複雑ではありません。

別のオプションは、関数ポインターの配列を作成することです (PaulR の提案)。

引数を取らない関数についてあなたの例が正しいと仮定しているので、次のようになります。

typedef void (*funcptr)(void);

funcptr funcarr[10000] = { func1, func2, .... func9999, func10000 };
// If coding standard allows 10 initializations on a row, you can even do it 
// in 102 lines. 

sel = hashfunction(string);
funcarr[sel]();   // Calls the function. 
于 2012-12-28T19:58:06.880 に答える