日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言常用的异常处理,C语言中的异常处理

發(fā)布時(shí)間:2025/4/5 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言常用的异常处理,C语言中的异常处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 前言:

異常處理,對于做面向?qū)ο箝_發(fā)的開發(fā)者來說是再熟悉不過了,例如在C#中有

try

{

...

}

catch( Exception e){...}

finally{

.....

}

在C++中,我們常常會使用

try{}

...

catch(){}

塊來進(jìn)行異常處理。

說了那么多,那么到底什么是異常處理呢?

異常處理(又稱為錯誤處理)功能提供了處理程序運(yùn)行時(shí)出現(xiàn)的任何意外或異常情況的方法。

異常處理一般有兩種模型,一種是"終止模型",一種是"恢復(fù)模型"

"終止模型":在這種模型中,將假設(shè)錯誤非常關(guān)鍵,將以致于程序無法返回到異常發(fā)生的地方繼續(xù)執(zhí)行.一旦異常被拋出,就表明錯誤已無法挽回,也不能回來繼續(xù)執(zhí)行.

"恢復(fù)模型":異常處理程序的工作是修正錯誤,然后重新嘗試調(diào)動出問題的方法,并認(rèn)為的二次能成功. 對于恢復(fù)模型,通常希望異常被處理之后能繼續(xù)執(zhí)行程序.在這種情況下,拋出異常更像是對方法的調(diào)用--可以在Java里用這種方法進(jìn)行配置,以得到類似恢復(fù)的行為.(也就是說,不是拋出異常,而是調(diào)用方法修正錯誤.)或者,把try塊放在while循環(huán)里,這樣就可以不斷的進(jìn)入try塊,直到得到滿意的結(jié)果.

二 面向?qū)ο笾械漠惓L幚?/p>

大致了解了什么是異常處理后,由于異常處理在面向?qū)ο笳Z言中使用的比較普遍,我們就先以C++為例,做一個(gè)關(guān)于異常處理的簡單例子:

問題:求兩個(gè)數(shù)相除的結(jié)果。

這里,隱藏這一個(gè)錯誤,那就是當(dāng)除數(shù)為0時(shí),會出現(xiàn),所以,我們得使用異常處理來捕捉這個(gè)異常,并拋出異常信息。

具體看代碼:

1?#include?

2?#include?

3?using?namespace?std;

4?class?DivideError:public?exception

5?{

6??public:

7???????????DivideError::DivideError():exception(){}

8??????????const?char*?what(){

9?????????????return?"試圖去除一個(gè)值為0的數(shù)字";

10?????????}

11

12?};

13?double?quotion(int?numerator,int?denominator)

14?{

15?????if(0==denominator)??????????//當(dāng)除數(shù)為0時(shí),拋出異常16?????throw?DivideError();

17?????return?static_cast(numerator)/denominator;

18?}

19?int?main()

20?{

21?????int?number1;?????????????//第一個(gè)數(shù)字22?????int?number2;?????????????//第二個(gè)數(shù)字23?????double?result;

24?????cout<

25?????while(cin>>number1>>number2){

26?????????try{

27?????????????result=quotion(number1,number2);

28?????????????cout<

29

30?????????}?????//end?try31?????????catch(DivideError?&divException){

32?????????????cout<

33?????????????????<

34?????????}

35?????}

36

37?}

38

在這個(gè)例子中,我們使用了頭文件中的exception類,并使DivideError類繼承了它,同時(shí)重載了虛方法what(),以給出特定的異常信息。

而C#中的異常處理類則封裝的更有全面,里面封裝了常用的異常處理信息,這里就不多說了。

三 C語言中的異常處理

在C語言中異常處理一般有這么幾種方式:

1.使用標(biāo)準(zhǔn)C庫提供了abort()和exit()兩個(gè)函數(shù),它們可以強(qiáng)行終止程序的運(yùn)行,其聲明處于頭文件中。

2.使用assert(斷言)宏調(diào)用,位于頭文件中,當(dāng)程序出錯時(shí),就會引發(fā)一個(gè)abort()。

3.使用errno全局變量,由C運(yùn)行時(shí)庫函數(shù)提供,位于頭文件中。

4.使用goto語句,當(dāng)出錯時(shí)跳轉(zhuǎn)。

5.使用setjmp,longjmp進(jìn)行異常處理。

接下來,我們就依次對這幾種方式來看看到底是怎么做的:

我們?nèi)耘f以前面處理除數(shù)為0的異常為例子。

1.使用exit()函數(shù)進(jìn)行異常終止:

1?#include?

2?#include?

3?double?diva(double?num1,double?num2)?????????//兩數(shù)相除函數(shù)4?{

5?????double?re;

6?????re=num1/num2;

7?????return?re;

8?}

9?int?main()

10?{

11????double?a,b,result;

12??printf("請輸入第一個(gè)數(shù)字:");

13???scanf("%lf",&a);

14???printf("請輸入第二個(gè)數(shù)字:");

15???scanf("%lf",&b);

16???if(0==b)????????????????????????????????//如果除數(shù)為0終止程序17???exit(EXIT_FAILURE);

18?result=diva(a,b);

19????printf("相除的結(jié)果是:?%.2lf\n",result);

20?return?0;

21?}

其中exit的定義如下:

_CRTIMP void __cdecl __MINGW_NOTHROW?exit?(int) __MINGW_ATTRIB_NORETURN;

exit的函數(shù)原型:void exit(int)由此,我們也可以知道EXIT_FAILURE宏應(yīng)該是一個(gè)整數(shù),exit()函數(shù)的傳遞參數(shù)是兩個(gè)宏,一個(gè)是剛才看到的EXIT_FAILURE,還有一個(gè)是EXIT_SUCCESS從字面就可以看出一個(gè)是出錯后強(qiáng)制終止程序,而一個(gè)是程序正常結(jié)束。他們的定義是:

#define?EXIT_SUCCESS?0

#define?EXIT_FAILURE?1

到此,當(dāng)出現(xiàn)異常的時(shí)候,程序是終止了,但是我們并沒有捕獲到異常信息,要捕獲異常信息,我們可以使用注冊終止函數(shù)atexit(),它的原型是這樣的:int atexit(atexit_t func);

具體看如下程序:

1?#include?

2?#include?

3?void?Exception(void)???????????????????????????//注冊終止函數(shù),通過掛接到此函數(shù),捕獲異常信息4?{

5?????printf("試圖去除以一個(gè)為0的數(shù)字,出現(xiàn)異常!\n");

6?}

7?int?main()

8?{

9????double?a,b,result;

10???printf("請輸入第一個(gè)數(shù)字:");

11???scanf("%lf",&a);

12???printf("請輸入第二個(gè)數(shù)字:");

13???scanf("%lf",&b);

14???if(0==b)????????????????????//如果除數(shù)為0終止程序?,并掛接到模擬異常捕獲的注冊函數(shù)15???{

16

17???atexit(Exception);

18???exit(EXIT_FAILURE);

19???}

20????result=diva(a,b);

21????printf("相除的結(jié)果是:?%.2lf\n",result);

22?return?0;

23?}

這里需要注意的是,atexit()函數(shù)總是被執(zhí)行的,就算沒有exit()函數(shù),當(dāng)程序結(jié)束時(shí)也會被執(zhí)行。并且,可以掛接多個(gè)注冊函數(shù),按照堆棧結(jié)構(gòu)進(jìn)行執(zhí)行。abort()函數(shù)與exit()函數(shù)類似,當(dāng)出錯時(shí),能使得程序正常退出,這里就不多說了。

2.使用assert()進(jìn)行異常處理:

assert()是一個(gè)調(diào)試程序時(shí)經(jīng)常使用的宏,切記,它不是一個(gè)函數(shù),在程序運(yùn)行時(shí)它計(jì)算括號內(nèi)的表達(dá)式,如果表達(dá)式為FALSE ?(0), ?程序?qū)?bào)告錯誤,并終止執(zhí)行。如果表達(dá)式不為0,則繼續(xù)執(zhí)行后面的語句。這個(gè)宏通常原來判斷程序中是否出現(xiàn)了明顯非法的數(shù)據(jù),如果出現(xiàn)了終止程序以免導(dǎo)致嚴(yán)重后果,同時(shí)也便于查找錯誤。

另外需要注意的是:assert只有在Debug版本中才有效,如果編譯為Release版本則被忽略。

我們就前面的問題,使用assert斷言進(jìn)行異常終止操作:構(gòu)造可能出現(xiàn)出錯的斷言表達(dá)式:assert(number!=0)這樣,當(dāng)除數(shù)為0的時(shí)候,表達(dá)式就為false,程序報(bào)告錯誤,并終止執(zhí)行。

代碼如下:

代碼

3.使用errno全局變量,進(jìn)行異常處理:

errno全局變量主要在調(diào)式中,當(dāng)系統(tǒng)API函數(shù)發(fā)生異常的時(shí)候,將errno變量賦予一個(gè)整數(shù)值,根據(jù)查看這個(gè)值來推測出錯的原因。

其中的各個(gè)整數(shù)值都有一個(gè)相應(yīng)的宏定義,表示不同的異常原因:

代碼

這里我們就不以前面的除數(shù)為0的例子來進(jìn)行異常處理了,因?yàn)槲也恢廊绾味x自己特定錯誤的errno,如果哪位知道,希望能給出方法。我以一個(gè)網(wǎng)上的例子來說明它的使用方法:

代碼

這里試圖打開一個(gè)d盤的文件,如果文件不存在,這是查看errno的值,結(jié)果是2、

當(dāng)文件存在時(shí),errno的值為初始值0。然后查看值為2的錯誤信息,在宏定義那邊#define????ENOFILE????????2????/*?No?such?file?or?directory?*/

便知道錯誤的原因了。

4.使用goto語句進(jìn)行異常處理:

goto語句相信大家都很熟悉,是一個(gè)跳轉(zhuǎn)語句,我們還是以除數(shù)為0的例子,來構(gòu)造一個(gè)異常處理的例子:

代碼

5.使用setjmp和longjmp進(jìn)行異常捕獲與處理:

setjmp和longjmp是非局部跳轉(zhuǎn),類似goto跳轉(zhuǎn)作用,但是goto語句具有局限性,只能在局部進(jìn)行跳轉(zhuǎn),當(dāng)需要跳轉(zhuǎn)到非一個(gè)函數(shù)內(nèi)的地方時(shí)就需要用到setjmp和longjmp。setjmp函數(shù)用于保存程序的運(yùn)行時(shí)的堆棧環(huán)境,接下來的其它地方,你可以通過調(diào)用longjmp函數(shù)來恢復(fù)先前被保存的程序堆棧環(huán)境。異常處理基本方法:

使用setjmp設(shè)置一個(gè)跳轉(zhuǎn)點(diǎn),然后在程序其他地方調(diào)用longjmp跳轉(zhuǎn)到該點(diǎn)(拋出異常).

代碼如下所示:

#include?

#include?

jmp_buf?j;

void?Exception(void)

{

longjmp(j,1);

}

double?diva(double?num1,double?num2)?????????//兩數(shù)相除函數(shù)?{

double?re;

re=num1/num2;

return?re;

}

int?main()

{

double?a,b,result;

printf("請輸入第一個(gè)數(shù)字:");

scanf("%lf",&a);

printf("請輸入第二個(gè)數(shù)字:");

if(setjmp(j)==0)

{

scanf("%lf",&b);

if(0==b)

Exception();

result=diva(a,b);

printf("相除的結(jié)果是:?%.2lf\n",result);

}

else

printf("試圖除以一個(gè)為0的數(shù)字\n");

return?0;

}

四 總結(jié):

除了以上幾種方法之外,另外還有使用信號量等等方法進(jìn)行異常處理。當(dāng)然在實(shí)際開發(fā)中每個(gè)人都有各種調(diào)式的技巧,而且這文章并不是說明異常處理一定要這樣做,這只是對一般做法的一些總結(jié),也不要亂使用異常處理,如果弄的不好就嚴(yán)重影響了程序的效率和結(jié)構(gòu),就像設(shè)計(jì)模式一樣,不能胡亂使用。

總結(jié)

以上是生活随笔為你收集整理的c语言常用的异常处理,C语言中的异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。