C:assert()及error()的使用

    bug:這個詞的本意是蟲子的意思,在計算機剛出來的時候,裏面都是發光發熱電子管,經常會吸引一些bug,通常會引起電子管的短路,所以那時候如果人們發現計算機無法工作,第一件事就是打開計算機看看是不是又飛進去了bug。現在bug的含義是缺陷。發現並修正的bug叫做debug
    錯誤(error):一般泛指結果和預期的不一樣,一類是設計實現錯誤,另一類是用戶操作引起的錯誤。我們希望能夠預見並有效處理的錯誤叫做Error-handle。
    異常(exception):這個詞是在C++語言中被引入的,C語言中並不支持異常。
bug主要引發三種錯誤:

編譯錯誤 不符合C語言基本語法要求 int i //沒有分號
運行錯誤 非法操作,如被零除或讀取非法內存 int i=0;5/i;//被零除
邏輯錯誤 算法級或邏輯級錯誤 if(i=0)//邏輯錯誤

    越複雜的設計,隱含的Bug就越多,所以,不僅需要程序簡潔,而且還需要程序員細心縝密。但是無論程序員再怎麼仔細也不能完全的避免Bug。所以在開發時,應當儘早的的發現並改正bug,而在C語言中,有一個有趣的函數,叫做assert斷言函數,能夠發現一些潛在的bug。
assert的三個基本知識:

  1. assert函數的原型爲void assert(int expression)。它的作用就是判斷表達式的邏輯值,如果其值爲假(爲0),它會先向stderr打印一條出錯信息,然後調用abort來終止程序。如果爲真,則什麼也不做。
  2. 頻繁調用會極大地影響程序的性能,增加額外開銷。
  3. 可以在#include<assert.h>的語句前面插入#define NDEBUG來禁用或者關閉assert。見下面代碼塊。
#include<stdio.h>
#define NDEBUG
#include<assert.h>

assert是用於軟件開發與測試階段,一般用於以下幾個方面。

在函數開始處檢驗出入參數的合理性
在調用庫函數之前,檢查出入參數合理性
檢查變量的合理性和一致性

我們用下面這段程序進行舉例:

void fun(char *p){
      assert(p!=NULL);
      ...
      }

    我們需要得到指針p的指向內容,一定會假設p不是一個空值,如果經過assert驗證後發現假設不成立,那麼調用fun函數部分一定存在問題。
常見的Debug工具
《C語言程序設計》給出了必須掌握的七種debug武器:

斷點
單步執行
監視窗
內存影響
函數調用棧
assert
fprintf

assert()的使用

assert()定義在頭文件assert.h中,它的原型爲

void assert(int expression)

assert()最常用的作用是檢查bug,當你不希望出現某些結果的時候可以利用這個函數進行檢驗,若是滿足判斷條件則不會有任何影響,若是不滿足條件,將會發出警告並停止程序運行。我們以下面的代碼爲例,要求輸入不能爲0,利用assert()進行校驗.

#include <stdio.h>
#include<assert.h>
int main()
{
	int x;
	scanf_s("%d", &x);//輸入x
	assert(x != 0);//bug判斷
	printf("%d\n", x);//輸出x
    return 0;
}

對應輸入不爲0和不爲0的結果如下圖:
在這裏插入圖片描述
在這裏插入圖片描述

錯誤(error)

    errno.h頭文件定義了多個用於定義和記錄運行時錯誤的宏。這些宏與perror()函數一起使用。perror()函數的頭文件是stdio.h。
    errno是一個外部int型變量,許多庫函數在函數運行期間發生錯誤,都會講一個值賦給該變量。即初始化errno爲0,不同錯誤下會得到一個不同的值,即判斷是否有錯誤。
    perror()是標準庫裏面另一個錯誤處理工具。調用時,會在stdeer上顯示一條消息,即根據errno的值給出錯誤描述。其調用格式爲:

void perror(const char *msg)

    msg爲可選的,用戶定義的值。常用的error值及perror()錯誤描述見下表。

名稱 錯誤描述
E2BIG 1000 參數列表過長
EACCES 5 沒有權限
EBADF 6 文件描述無效
EDOM 1002 數學參數超出值域
EEXIST 80 文件已存在
EMFILE 4 打開文件過多
ENOENT 2 文件或路徑無效
ENOEXEC 1001 執行格式錯誤
ENOMEM 8 內存不夠
ENOPATH 3 未找到路徑
ERANGE 1003 結果超出範圍

    我們給出一個例子,利用errno和perror來確定具體錯誤。sqrt()是開方運算,需要值大於0,如果我們給予其一個小於零的數,參數會在範圍外。其實現代碼爲:

#include <stdio.h>
#include<errno.h>
#include<stdlib.h>
#include<math.h>
int main()
{
	errno = 0;
	sqrt(-1.0);
	if (errno > 0) {
		perror("sqrt");
	}
    return 0;
}

運算結果爲
在這裏插入圖片描述
    我們經常進行文件操作,也可以用於文件權限操作是否實現的驗證。如下:

#include <stdio.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
	FILE *fp;
	errno_t err;
	err = fopen_s(&fp,"a", "r+");
	if (fp == NULL) {
		printf("%d\n", errno);
		perror("a");
	}
    return 0;
}

    運行結果:
在這裏插入圖片描述
參考Bradley Jones.Peter Aitken.Dean Miller的《21天學通C語言》
參考趙巖的《c語言點滴》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章