3

我有一个包含数千个或更多独特案例的 switch case 语句。用户很难通过案例编号记住每个案例。所以,我为每种情况使用一个唯一的字符串并对其进行散列以获得给定字符串的选择“sel”:

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

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

但是,此代码变得非常大,因为它必须位于单个文件中,并且还违反了 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 source.c -Wall -ldl -rdynamic

请记住,编译-rdynamic会增加可执行文件的大小。

于 2012-12-28T18:58:10.637 回答
3

如果所有情况都是简单的函数调用[希望不调用 func1、func2、func3 等],那么我相信一个长的 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 回答