欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

C語言程序開發中,難免會出現邏輯錯誤,怎樣讓程序自己輸出錯誤位置呢?

劉柏宏2年前14瀏覽0評論

謝邀。

在C語言程序開發中,程序員常常會把一個復雜的任務拆分成若干個較為簡單的子模塊,這些子模塊可以看做是復雜任務的各個組成部分。因此,程序員將子模塊逐個完成后,就可以將其像“積木”一樣搭建起來,進而解決復雜任務。

之所以要這么做,是因為若直接編寫C語言代碼一次性解決復雜任務,往往會讓整個代碼“揉作一團”,不僅開發時容易引入bug,而且后期維護起來也比較痛苦。想象一下,若將任務拆分成若干個子模塊,以后發現問題時,可能只需要修改某個子模塊就可以了。但是若沒有這么做,查找和解決問題就必須對全部代碼下手了。哪一種開發風格維護起來方便,相信題主自然明白。

將任務拆分成子模塊后,每個子模塊常常被封裝成一個C語言函數,所以,最后的“堆積木”其實就是調用各個C語言函數。不過,每一個子模塊都有可能得到正常結果,也有可能得到異常結果,這通常用C語言函數的返回值區分。在“堆積木”階段調用各個函數時,應該根據被調用函數的返回值做不同的處理。

例如,某個子模塊負責計算用戶輸入數字的log(對數)值時,如果用戶輸入的是正數,則該子模塊能夠得到正常的結果。但如果用戶輸入的是負數,子模塊顯然就無法得到正常結果了。

下面是一個例子

這里的例子C語言代碼盡可能的簡單,是為了將重心放在討論主題上:

cond()函數產出0~10的隨機數,如果隨機數小于5就返回-1(模擬異常結果),否則返回0(模擬正常結果)。fun1()函數和fun2()函數都會根據cond()函數的返回值做一些進一步的工作(上面的C語言代碼略過了“進一步工作”)。在main()函數中“堆積木”調用fun1()和fun2()函數時,使用了if語句判斷它們的返回值,并且根據返回值做了不同的處理。

現在編譯這段C語言程序并執行,得到如下結果:

從輸出結果可以發現,C語言程序輸出了“condisfalse”(模擬異常)。我們往往不希望程序輸出異常結果,所以看到異常結果后,就需要知道為什么會出現這個結果。

適當的輸出信息有利于定位異常

查看C語言源代碼,發現程序輸出異常結果是因為main()函數里的if(!fun1()&&!fun2())為假,但是無論fun1()還是fun2()返回-1,都會導致if條件表達式為假,這么看來,main()函數調用fun1()和fun2()函數的方式就不太合適了,因為到這里我們已經無法繼續追蹤異常原因了。似乎main()函數這么寫更合適,相關C語言代碼如下,請看:

編譯修改后的C語言代碼并執行,得到如下結果:

這次我們就知道異常輸出是哪個函數導致的了,不過僅調用兩個函數就寫了這么多行極有可能用不到的錯誤提示代碼,太麻煩了,如果其他地方也需要用到類似的調用,就更麻煩了,有沒有更方便的方法呢?我們嘗試將錯誤提示信息塞入fun1()和fun2()函數試試,如下修改fun1()和fun2()函數的代碼:

現在使用修改之前的main()函數如下:

編譯并執行這段C語言代碼并執行,得到如下輸出:

這樣一來,我們既能根據輸出推斷異常是由哪個函數導致的,也能盡可能的保持C語言代碼的簡潔性。不過代碼還是有一點點啰嗦:

這兩句輸出僅有fun1和fun2是不同的,但是我們卻需要完整的寫兩遍幾乎一樣的語句,而且以后萬一需要修改,還需要兩處都修改,一來麻煩,二來容易出錯。能不能避免這種情況呢?

使用__FUNCTION__,__LINE__,__FILE__等關鍵字

在C語言程序的編譯階段,編譯器會將__FUNCTION__,__LINE__,__FILE__這幾個關鍵字解釋為“所在函數名”,“所在行號”,“所在文件名”。所以有了這幾個關鍵字,我們就沒有必要再手動輸入函數名了,針對本節提到的例子,完全可以使用上一節介紹的define宏定義:

編譯并執行這段C語言代碼,得到如下結果:

可以看出,程序不僅把異常的函數名輸出了,還把該函數所在的文件名(t.c)以及行號(line:26,line:41)輸出了,這樣的調試信息看起來非常舒服,在大型項目開發中,實用性很強。

類似的調試宏還有TIMEDATE等,就不一一演示了。

小結

本節討論了在C語言程序開發中,復雜任務常被拆分成多個子模塊并一一封裝為函數,這些函數可能有正常處理結果,也有可能有異常處理結果,所以本節討論了輸出基本調試信息對定位問題的重要性,并在最后介紹了幾種C語言程序開發常用的調試宏,這些宏在大型項目開發中實用性很強。

歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。