c/c++的异常统一处理
2012-11-07 23:01 钱吉 阅读(1398) 评论(0) 编辑 收藏 举报今天看HTK代码,发现里面的错误处理机制很好,所以自己在这里总结一下。如何将某些类型的错误集中起来统一处理,使得程序易于维护和具有更好的可读性。
这里假设有这样一个故事,有个美女征婚,理想中的男人如果要表白成功,需要具备6个条件:玫瑰(Rose),戒指(Ring),宝马(BWM),高(Tall),富(Rich),帅(Handsome)。(好吧,我承认这个故事很低俗,但是实在想不出其它例子来比喻了,将就着看吧,-_-)。如果少了一个条件,sorry,美女要抛出异常了。但是现在求婚的人太多,美女无暇顾及,所以决定先请人把关,再根据把关人反馈的结果统一处理。好了,先看C语言如何处理:
C语言错误统一处理
1 #include <stdio.h> 2 #include <memory.h> 3 #include <stdarg.h> 4 #define COUNT 6 5 static char *pall[]={"Ring", "Rose", "BMW", "Tall", "Rich", "Handsome"}; 6 7 8 typedef struct _Condition { 9 char *pgift[COUNT]; 10 int ngift; 11 }Condition;//存储个人条件的结构体 12 static void Select(const Condition *con); 13 static void Herror(int ntype, char *str, ...); 14 int main(int argc, char **argv) 15 { 16 Condition A,B,C; 17 memset(A.pgift, 0, COUNT); 18 memset(B.pgift, 0, COUNT); 19 memset(C.pgift, 0, COUNT); 20 A.pgift[1]=pall[1]; A.ngift=1;//A->Rose 21 B.pgift[0]=pall[0]; B.pgift[5]=pall[5]; B.ngift=2;//B->Ring,Handsome 22 C.pgift[1]=pall[1]; C.pgift[2]=pall[2]; C.pgift[4]=pall[4]; C.ngift=3;//C->Rose,BMW,Rich 23 24 Select(&A); 25 Select(&B); 26 Select(&C); 27 return 0; 28 } 29 /***************************************** 30 *根据条件考虑每个人,并调用错误统一处理函数 31 ******************************************/ 32 static void Select(const Condition *con) 33 { 34 if(con==NULL) 35 return; 36 switch(con->ngift) 37 { 38 case 0: 39 break; 40 case 1: 41 Herror(1, "fail:only have %s", con->pgift[1]); 42 break; 43 case 2: 44 Herror(2, "fail:only have %s,%s", con->pgift[0], con->pgift[5]); 45 break; 46 case 3: 47 Herror(3, "fail:only have %s,%s,%s", con->pgift[1], con->pgift[2], con->pgift[4]); 48 break; 49 default: 50 break; 51 } 52 } 53 /******************************************** 54 * 统一处理 55 * *****************************************/ 56 static void Herror(int ntype, char *str, ...) 57 { 58 va_list parg; 59 FILE *f = stdout; 60 va_start(parg, str);//获取指向可变参数的第一个参数的指针 61 printf("\n---------Result--------\n"); 62 if(ntype < 3) 63 printf("pass over:"); 64 else if(ntype < 5) 65 printf("just so so:"); 66 else 67 printf("wait and see:"); 68 vfprintf(f, str, parg);//输出结果 69 printf("\n----------over---------\n"); 70 va_end(parg);//关闭指针 71 fflush(f); 72 }
结构体中的ngift表示男人征婚准备的礼物数量。32行的select函数所做的工作就是把关,考擦每个男人的条件,对于不符合美女要求的,统一把把关结果反馈给Herror函数,这里Herror做的事情就是美女根据反馈结果下结论:ngift<3的直接pass掉(这美女有点物质,哈哈),介于3与5之间的她觉得一般般,只有大于5时,她决定再看看。这就完成了错误的处理过程。
值得说一下的是,Herror的最后参数是一个可变形参,所以具有更大的灵活性,便于程序的扩展。其中可变形参的获取用到了va_start和va_end宏,这个宏在标准库<stdarg.h>中定义。详细的使用说明可以去网上搜一下。
C++的统一异常处理
C++提供了异常处理的一个类:exception。为了解决我们自己碰到的异常,只需要继承这个类,并重载或自定义一些错误处理函数即可实现。同样是上面的列子,我们改动一下:
1 #include <iostream> 2 #include <cstdlib> 3 using namespace std; 4 #define COUNT 6 5 static char *pall[]={"Ring", "Rose", "BMW", "Tall", "Rich", "Handsome"}; 6 7 typedef struct _Condition { 8 char *pgift[COUNT]; 9 int ngift; 10 }Condition; 11 12 class MyException:public exception 13 { 14 public: 15 MyException():m_ntype(-1),m_str(NULL) {} 16 MyException(int n, char *p):m_ntype(n),m_str(p) {} 17 char* Deal() const throw(); 18 ~MyException() 19 { 20 if(m_str) 21 { 22 delete m_str; 23 m_str = NULL; 24 } 25 } 26 private: 27 int m_ntype; 28 char *m_str; 29 }; 30 static void Select(const Condition *con); 31 32 int main(int argc, char **argv) 33 { 34 Condition A,B,C; 35 Condition *pcon[3]; 36 memset(A.pgift, 0, COUNT); 37 memset(B.pgift, 0, COUNT); 38 memset(C.pgift, 0, COUNT); 39 A.pgift[1]=pall[1]; A.ngift=1;//A->Rose 40 B.pgift[0]=pall[0]; B.pgift[5]=pall[5]; B.ngift=2;//B->Ring,Handsome 41 C.pgift[1]=pall[1]; C.pgift[2]=pall[2]; C.pgift[4]=pall[4]; C.ngift=3;//C->Rose,BMW,Rich 42 pcon[0] = &A; pcon[1] = &B; pcon[2] = &C; 43 44 for (int i=0; i<3; i++) 45 { 46 try 47 { 48 Select(pcon[i]); 49 } 50 catch (MyException &e) 51 { 52 char *ptemp; 53 ptemp = e.Deal(); 54 if (ptemp!=NULL) 55 { 56 printf("\n---------Result--------\n"); 57 cout<<ptemp<<endl; 58 printf("\n----------over---------\n"); 59 delete ptemp; 60 } 61 } 62 } 63 return 0; 64 } 65 /***************************************** 66 *根据条件考虑每个人,并调用错误统一处理函数 67 ******************************************/ 68 static void Select(const Condition *con) 69 { 70 char *presult; 71 if(con==NULL) 72 return; 73 if (NULL == (presult = new char[1024])) 74 { 75 exit(1); 76 } 77 switch(con->ngift) 78 { 79 case 0: 80 break; 81 case 1: 82 sprintf(presult,"fail:only have %s",con->pgift[1]); 83 throw MyException(1, presult); 84 break; 85 case 2: 86 sprintf(presult,"fail:only have %s,%s", con->pgift[0], con->pgift[5]); 87 throw MyException(2, presult); 88 break; 89 case 3: 90 sprintf(presult,"fail:only have %s,%s,%s",con->pgift[1], con->pgift[2], con->pgift[4]); 91 throw MyException(3, presult); 92 break; 93 default: 94 break; 95 } 96 } 97 char* MyException::Deal() const throw() 98 { 99 char *pstr = new char[1024]; 100 if (pstr == NULL) 101 return NULL; 102 if(m_ntype < 3) 103 sprintf(pstr,"pass over:%s",m_str); 104 else if(m_ntype < 5) 105 sprintf(pstr,"just so so:%s",m_str); 106 else 107 sprintf(pstr,"wait and see:",m_str); 108 return pstr; 109 }
利用C++的try/catch/throw框架即可捕获异常,在把关的select函数中,我们有自定义的异常类MyException对象,将相关信息写进类中,然后抛出。在catch中捕获以后,调用类的Deal函数对异常进行统一处理。如果以后美女的想法改变,只有达到了5项条件的才算正常,那我们只需要修改Deal函数就可以了。