如何减少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函数,它们需要更多参数,所以我不能只创建一个宏。
答案 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)
将所有名称和功能存储在结构中:
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
之前添加“成功”标记,或在底部测试i == sizeof(calc_routine) /sizeof(calc_routine[0])
。)
这具有初始优势,您可以随意添加,随机播放和删除任何子例程。
一旦确定了最终的名称/功能集,请按名称对它们进行一次排序,然后使用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保留函数指针数组。
它会减少代码大小。