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

今天看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函数就可以了。

你可能感兴趣的:(c/c++)