简体   繁体   中英

Equivalent compact “Switch Case” statement

I have a switch case statement with thousands or more unique cases. It's difficult for an user to remember each case by the case number. So, I am using a unique string for each case and hashing it to get the selection 'sel' for the given string:

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

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

However, this code becomes quite large as it has to be in a single file and also violates the coding guideline of say 100 lines. As there is a unique mapping of the cases to the function calls, I presume I can use pointer to function in side a for loop to call them. This will be very compact than the switch case. Any help to achieve this is greatly appreciated.

If each of your functions have the same type and naming convention, and if you're on POSIX, you can use the dynamic linking loader to compute the name of the function to call and execute it dynamically.

Per example:

#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)();
}

Here, calling call_some_func(1) would execute func1() , etc.

In order for this to work, you will need to link the dl library and export the executable's symbols. In GCC:

gcc source.c -Wall -ldl -rdynamic

Keep in mind that compiling with -rdynamic will increase the executable size.

If all the cases are simple function calls [hopefully not called func1, func2, func3, etc], then I believe that one long switch statement is the cleanest, easiest way to solve this problem. Coding standard be damned - it's not complex enough to make it worthwhile doing something else, in my book.

Another option would be to build an array of function pointers (PaulR's suggestion):

I'm assuming your example is correct about the functions taking no arguments, so :

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. 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM