如何减少像这样的长 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/