Long if ...

How to reduce the long, if ..., such an operator?

if( strcmp( alnumToc, "log") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_log( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "log2") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_log2( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "log10") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_log10( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "sqrt") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_sqrt( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "cbrt") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_cbrt( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "abs") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_abs( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "sin") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_sin( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "cos") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_cos( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "csc") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_csc( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "cot") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_cot( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "acos") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_acos( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "asin") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_asin( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "atan") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_atan( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "cosh") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_cosh( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        } else if( strcmp( alnumToc, "sinh") == 0){
            ARGNUMCHECK( in, 1);
            mpfr_sinh( num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
        }

It is not just ugly, but also slow. I was thinking about using a hash table with function pointers. This is a good decision?
Note: there will be some mpfr functions that will contain more arguments, so I cannot create only one macro.

+4
source share
4 answers
  • Save all names and functions in a structure:

    struct calcRoutine_t {
      const char *name;
      void (*function)(int, int, int);
    } calc_routine[] = {
      { "log",  mpfr_log },
      { "log2", mpfr_log2 },
      { "log10",    mpfr_log10 },
      { "sqrt", mpfr_sqrt },
      { "cbrt", mpfr_cbrt },
      { "abs",  mpfr_abs },
      { "sin",  mpfr_sin },
      { "cos",  mpfr_cos },
      { "csc",  mpfr_csc },
      { "cot",  mpfr_cot },
      { "acos", mpfr_acos },
      { "asin", mpfr_asin },
      { "atan", mpfr_atan },
      { "cosh", mpfr_cosh },
      { "sinh", mpfr_sinh }
    };
    
  • Scroll through the array and use strcmpto find the correct function:

    for (i=0; i<sizeof(calc_routine)/sizeof(calc_routine[0]); i++)
    {
        if (!strcmp ( calc_routine[i], alnumToc) )
        {
            ARGNUMCHECK( in, 1);
            calc_routine[i].function (num, stack[j-1], MPFR_RNDN);
            CPYRES( 1);
            break;
        }
    }
    

    (You can add the โ€œsuccessโ€ flag before breakor check if i == sizeof(calc_routine) /sizeof(calc_routine[0])below.)

, , .

/, bsearch . bsearch , ; bsearch NULL.

, , 1. struct calcRoutine_t .

+4

, , . .

- , bsearch . , . .

, :

typedef struct
{
  const char*  STRING;
  func_t       action;
} my_str_thing;

const my_str_thing TABLE [N] =
{
  { "ABC", do_this},
  { "DEF", do_that},
  ...
};

-, .

+5

- , strcmp .

, , alnumToc , . :

switch(alnumToc[0]) {
  case 'a': // abs, acos, asin or atan, you don't have to check beyond alnumToc[1]
    switch(alnumToc[1]) {
      case 'b'
        // deal with "abs"
        break;
      case 'c'
        // deal with "acos"
        break;
      case 's'
        // deal with "asin"
        break;
      case 't'
        // deal with "atan"
        break;
    }
    break;

  case 'l': // log, log2, or log10, "og" is common, no need to check
    switch(alnumToc[3]) {
      case '\0' // terminator of c string
        // deal with "log"
        break;
      case '2'
        // deal with "log2"
        break;
      case '1'
        // deal with "log10"
        break;
    }
    break;
  // you can figure out the rest
}

The bottom line is only a scan alnumToconce for best performance. If you cannot guarantee that it is alnumTocclean, print everything alnumToc[0], [1], [2], ....

+1
source

1. Instead, save all rows in an array.

char *strarray[] = {"log", "log2", "blah Blah"};

2. Run the for loop, for example

for(i = 0; i < NO_OF_STRINGS; i++)
{
    // strcmp
}   

3. Store an array of function pointers for mpfr_sqrt, mpfr_acos, ..

This will reduce the size of the code.

0
source

Source: https://habr.com/ru/post/1546970/


All Articles