c/c++的异常统一处理

长平狐 发布于 2013/03/12 13:02
阅读 133
收藏 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 * sult; 71 if(con== NULL) 72 return ; 73 if (NULL == (sult = new char[ 1024 ])) 74 { 75 exit( 1 ); 76 } 77 switch(con-> ngift) 78 { 79 case 0 : 80 break ; 81 case 1 : 82 sprintf(sult, " fail:only have %s ",con->pgift[ 1 ]); 83 throw MyException( 1 , sult); 84 break ; 85 case 2 : 86 sprintf(sult, " fail:only have %s,%s ", con->pgift[ 0], con->pgift[ 5 ]); 87 throw MyException( 2 , sult); 88 break ; 89 case 3 : 90 sprintf(sult, " fail:only have %s,%s,%s ",con->pgift[ 1], con->pgift[ 2], con->pgift[ 4 ]); 91 throw MyException( 3 , sult); 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函数就可以了。


原文链接:http://www.cnblogs.com/wb-DarkHorse/archive/2012/11/07/2759380.html
加载中
返回顶部
顶部