很长的if..else声明

时间:2014-07-03 08:54:16

标签: c if-statement

如何减少if..else这样的long语句?

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

这不仅丑陋而且缓慢。我想过使用带有函数指针的哈希表。那是好的解决方案吗? 注意:会有一些mpfr函数,它们需要更多参数,所以我不能只创建一个宏。

4 个答案:

答案 0 :(得分:5)

这是非常糟糕的代码,实际上它会非常慢。它必须从头开始重写。

最快的方法是将所有字符串文字存储在已排序的数组中,然后使用bsearch进行搜索。使用字符串数组,其中字符串是搜索键。您必须为结构类型编写自己的比较函数。

如果找到要查找的字符串,请通过函数指针调用其对应的函数:

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

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

哈希表也可以解决,但对于这种特殊情况似乎不必复杂。

答案 1 :(得分:4)

  1. 将所有名称和功能存储在结构中:

    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 }
    };
    
  2. 循环遍历数组并使用strcmp找到正确的函数:

    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;
        }
    }
    

    (您可以在break之前添加“成功”标记,或在底部测试i == sizeof(calc_routine) /sizeof(calc_routine[0])。)

  3. 这具有初始优势,您可以随意添加,随机播放和删除任何子例程。

    一旦确定了最终的名称/功能集,请按名称对它们进行一次排序,然后使用bsearch代替此循环。成功时,bsearch将指向正确的结构成员,您可以立即调用其关联的函数;如果失败,bsearch将返回NULL

    添加

    如注释中所述,某些函数可能需要的参数多于1.此数字也可以存储在结构calcRoutine_t中,以便在循环中进行测试。

答案 2 :(得分:1)

性能问题来自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
}

底线是仅扫描alnumToc一次以获得最佳效果。如果您无法保证alnumToc是干净的,请使用所有alnumToc[0], [1], [2], ...

答案 3 :(得分:0)

1。而是将所有字符串保留在数组中。

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

2. 运行类似

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

3. 为mpfr_sqrt,mpfr_acos保留函数指针数组

它会减少代码大小。