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

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 函数,需要更多的参数,所以我不能只创建一个宏。

最佳答案

  • 将所有名称和函数存储在一个结构中:
    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 }
    };
    
  • 循环遍历数组并使用 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 之前添加一个 'success' 标志,或者测试底部是否有 i == sizeof(calc_routine) /sizeof(calc_routine[0])。)

  • 这具有最初的优势,您可以随意添加、洗牌和删除任何子例程。

    一旦你决定了最后一组名称/函数,就按名称对它们进行一次排序,然后使用 bsearch 而不是这个循环。成功后,bsearch 将指向正确的结构成员,您可以立即调用其关联函数;失败时, bsearch 将返回 NULL

    添加

    正如评论中所指出的,某些函数可能需要比 1 更多的参数。这个数字也可以存储在 struct calcRoutine_t 中,以便在循环中进行测试。

    关于c - 长 if..else 语句,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24549204/

    10-11 22:06
    查看更多