2009-10-09 73 views
3

我有这个巨大的开关案例与嵌套开关案例陈述,我想知道如果任何人有任何想法如何清理?关于缩小这个功能的c个想法?

switch (datatype) { 
    case STR: 
    { 
     switch(operation) 
     { 
       case EQUALS: 
       { 
        /* perform str compare */ 
       } 
       case NOTEQUALS: 
       { 
       } 
       case LT: 
       { 
       } 
       case GT: 
       { 
       } 
       case GTE: 
       { 
       } 
       case LTE: 
       { 
       } 
       default: 
       break; 
     } 
     break; 
    } 
    case VER: 
    { 
     switch(operation) 
     { 
       case EQUALS: 
       { 
        /* perform version compare */ 
       } 
       case NOTEQUALS: 
       { 
       } 
       case LT: 
       { 
       } 
       case GT: 
       { 
       } 
       case GTE: 
       { 
       } 
       case LTE: 
       { 
       } 
       default: 
       break; 
     } 
     break; 
    } 
    case INT: 
    { 
     /* same */ 
    } 
    case FLOAT: 
    { 
     /* same */ 
    } 
    /* ... more types ... */ 
    /* ... .......... ... */ 
    default: 
     break; 
} 
+0

我可以问为什么有必要缩小这个? – 2009-10-10 04:49:30

回答

11

如果该操作的值是连续的,则可以创建一个函数指针表。事实上,你可以用一个单独的函数来创建一个2D函数指针表,以处理每个操作/类型组合。例如

// do some range checking on input params 
// invoke the handler 
handlers[datatype][operation](); 
+2

你可能想做一些验证,说明'datatype'和'operation'在正确的范围内,否则会发生坏事。 – rmeador 2009-10-09 16:37:11

+0

实际上,现代编译器会自动将大型开关转换为跳转表(并进行范围检查) – hirschhornsalz 2009-10-09 16:55:16

+3

@drhirsch:这不是关于性能,而是关于制作干净的代码。 – rmeador 2009-10-09 17:17:50

0

您可以使用大量的函数指针,然后根据索引将相关函数调用到数组中的正确函数指针。

5

使用指向其中函数的指针创建一些表(数组)。然后,您可以查找func[STR][EQUALS]以进行适当的呼叫。呼叫最终会变成这样......

Func[datatype][operation](); 
2

NOTEQUALS情况下,总是可以写在EQUALS箱子条款;根据GELTLTE类似地GTE。因此,按照operation制作外部开关,并且这六个案例中只有三个需要打开datatype

+1

并不总是如果你考虑部分排序。 – liori 2009-10-09 22:35:12

0

你有没有考虑过创造性地使用一系列函数指针并将它们存储在一个结构中?

做是正确的,你可以模仿的对象,做一些像这样:

bool someArbitraryFunction (dataType aDatatype, operations anOperation) 
{ 
someUnknownStruct.datatype = aDatatype; 
someUnknownStruct.operation = anOperation; 
return someUnknownStruct->doMath(1,2); 
} 

,然后你就可以把所有需要的数学函数,枚举和结构在头文件中的某个地方。

清理代码的“肉”,并使数学便携式(只需将它导入任何你需要的地方)。

0

假设你的情况下,都可以返回一个简单的布尔值,所有的六个逻辑的情况下可以在LT方面被改写,等于,就像如下:

switch(operation) { 
    case EQUALS: 
    return isEquals(); 
    case NOTEQUALS: 
    return !isEquals(); 
    case LT: 
    return isLT(); 
    case GT: 
    return !isLT() && !isEquals(); 
    case GTE: 
    return !isLT(); 
    case LTE: 
    reutrn isLT() || isEquals(); 
    default: 
    break; 
} 

这只会要求你写ISLT逻辑()和isEquals(),它们将在必要时进行数据类型切换。这消除了大量不必要的代码重复,但不会牺牲很多易读性。

这可以与Stephen Doyle和rikh已经提出的函数指针结合起来,这将完全消除switch()语句。