Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 903
Shan Avatar asked Feb 27 '26 02:02

Shan


2 Answers

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.

like image 156
netcoder Avatar answered Feb 28 '26 19:02

netcoder


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. 
like image 30
Mats Petersson Avatar answered Feb 28 '26 19:02

Mats Petersson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!