首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

优化if else 跟 switch case 结构

2012-09-01 
优化if else 和 switch case 结构简单:if -else 和switch-case 是我们经常见到的一个普通编程技术。他们所

优化if else 和 switch case 结构

简单:

if -else 和switch-case 是我们经常见到的一个普通编程技术。他们所生成的代码按照顺序进行比较,如果发现匹配,程序就会跳转到满足条件的语句上执行。

优化建议1:

按照他们发生的相对频率来进行排序,把最可能发生的情况放在第一位,最不可能的情况放在最后一位。

另外如过case 语句比较多,为了减少比较次数,建议把switch转化为嵌套的switch语句。即把频率高的的case,放在一个switch中,并且是switch语句的最外层,把频率低的case放在另外一个switch中。

复杂:

如果这种判断逻辑很多,很显然不易于维护和阅读,推荐使用“表驱动”的方法。

表驱动法(Table driven method),市一中不必用很多的逻辑语句就可以把表中的信息找出来的方法。它市一中设计模式,可以用来代替复杂的if-else 和switch-case逻辑判断。从某种意义上说,任何信息都可以通过“表”来进行选择。

在表相对简单的情况下,逻辑语句往往更简单,更直接。但随着逻辑链的复杂,表就变的越来越富有吸引力了。

初始表驱动:

例子:求每月的天数(不考虑闰年的情况,这个不是我们关注的重点)

一般的代码(C++):

[cpp] view plaincopyprint?
  1. int GetMonthDays(int iMonth)  
  2. {  
  3.     int iDays;  
  4.     if(1== iMonth) {iDays =31;}  
  5.     else if(2  == iMonth)  {iDays =28;}  
  6.     else if(3  == iMonth)  {iDays =31;}  
  7.     else if(4  == iMonth)  {iDays =30;}  
  8.     else if(5  == iMonth)  {iDays =31;}  
  9.     else if(6  == iMonth)  {iDays =30;}  
  10.     else if(7  == iMonth)  {iDays =31;}  
  11.     else if(8  == iMonth)  {iDays =31;}  
  12.     else if(9  == iMonth)  {iDays =30;}  
  13.     else if(10 == iMonth) {iDays =31;}  
  14.     else if(11 == iMonth) {iDays =30;}  
  15.     else if(12 == iMonth) {iDays =31;}  
  16.     return iDays;  
  17. }  

上述代码显的就比较笨拙了,代码比较冗长,可读性也比较低。

表驱动方法(C++):

[cpp] view plaincopyprint?
  1. static int s_nMonthdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};  
  2. int GetMonthDays(int iMonth)  
  3. {  
  4.     return s_nMonDays[(iMonth - 1)];  
  5. }  


也许你会有疑问,还是if-esle比较顺手啊,但对于十分冗长的switch-case或if-else最好还是能想办法将其化解开,方法有很多种:

选择函数封装?选择宏?还是选择表驱动?

带着疑问我们还是用例子进行说明比较妥帖些。

1.switch - case (分支越多可读性就越差,维护起来也很麻烦)

[cpp] view plaincopyprint?
  1. #define UN_DEFINED 0  
  2. #define PROCESSA 1  
  3. #define PROCESSB 2  
  4. #define PROCESSC 3  
  5. #define PROCESSD 4  
  6.   
  7.   
  8.   
  9. int ProcessControl(UINT function_no, void* para_in, void* para_out)  
  10. {  
  11.     int result;  
  12.     switch(function_no)  
  13.     {  
  14.         case PROCESSA:  
  15.             return = ProcessA(para_in,para_out);  
  16.             break;  
  17.         case PROCESSB:  
  18.             return = ProcessB(para_in,para_out);  
  19.             break;  
  20.         case PROCESSC:  
  21.             return = ProcessC(para_in,para_out);  
  22.             break;  
  23.         // 此处省略很多   case 标签  
  24.               
  25.         default:  
  26.             result = UN_DEFINED;  
  27.             break;  
  28.     }  
  29.     return result;  
  30. }  

[cpp] view plaincopyprint?
  1. int ProcessA(void* para_in, void* para_out)  
  2. {  
  3.     // code here   
  4. }  
  5. int ProcessB(void* para_in, void* para_out)  
  6. {  
  7.     // code here   
  8. }  
  9. int ProcessC(void* para_in, void* para_out)  
  10. {  
  11.     // code here   
  12. }  
  13.   
  14. // other similar function  

2 宏定义版本

[cpp] view plaincopyprint?
  1. #define DISPATCH_BEGIN(func)        switch(func)  \  
  2. {  
  3.   
  4. #define DISPATCH_FUNCTION(func_c,function) case func_c: \  
  5.     result = function(para_in,para_out);\  
  6.     break;  
  7.   
  8. #define DISPATCH_END(code)      default: \  
  9.     result = code; \  
  10. }  
  11.   
  12. // PROCESSA  processA 等定义同例1  
  13. int ProcessControl(UINT function_no, void* para_in, void* para_out)  
  14. {  
  15.     int result;  
  16.     DISPATCH_BEGIN(function_no)  
  17.         DISPATCH_FUNCTION(PROCESSA,processA)  
  18.         DISPATCH_FUNCTION(PROCESSB,processB)  
  19.         DISPATCH_FUNCTION(PROCESSC,processC)  
  20.         // omit many similar things  
  21.   
  22.     DISPATCH_BEGIN(UN_DEFINED)  
  23.     return result;  
  24. }  
  25.       
这个版本,稍稍有点感觉,但是这种方法治标不治本。还是看看表驱动如何实现的吧 。

3 表驱动(数组版本)

[cpp] view plaincopyprint?
  1. typedef struct tagDispathItem  
  2. {  
  3.     UINT function_no;  
  4.     ProcessFuncPtr func_ptr;  
  5. }DISPATCH_ITEM;  
  6. DISPATCH_ITEM dispatch_table(MAX_DISPATCH_ITEM);  
  7.   
  8. int ProcessControl(UINT function_no, void* para_in, void* para_out)  
  9. {  
  10.     int i;  
  11.     for(i = 0;i<MAX_DISPATCH_ITEM;++i)  
  12.     {  
  13.         if(function_no == dispatch_table[i].func_no)  
  14.         {  
  15.             return dispatch_table[i].funcptr(para_in,para_out);  
  16.         }  
  17.     }  
  18.     return UN_DEFINED;  
  19. }  

4.表驱动(高级数据结构)

[cpp] view plaincopyprint?
  1. typedef std::hash_map<UINT,ProcessFuncPtr> CmdHandlerMap;  
  2. CmdHandlerMap HandlerMap;  
  3.   
  4. void InitHandlerMap()  
  5. {  
  6.     HandlerMap[PROCESSA]=processFuncPtr(&ProcessA);  
  7.     HandlerMap[PROCESSB]=processFuncPtr(&ProcessB);  
  8.     HandlerMap[PROCESSC]=processFuncPtr(&ProcessC);  
  9.     // omit other many similar code  
  10. }  
  11.   
  12. int ProcessControl(UINT function_no, void* para_in, void* para_out)  
  13. {  
  14.     CmdHandlerMap::iterator it = HandlerMap.Find(function_no);  
  15.     if(it != HandlerMap.end())  
  16.     {  
  17.         ProcessFuncPtr pHandler = it->second;  
  18.         return (*pHandler)(para_in,para_out);  
  19.     }  
  20.     return UN_DEFINED;  
  21. }  

由此看来,表驱动的好处就是ProcessControl的代码就几行,逻辑不会改变。如添加新功能的时候,只要维护dispatch_table或HandlerMap就可以了。

到此你终于可以和switch-case 和 if-else 说 good-bye。


热点排行