三個必要的頭文件
#include <stdio.h>
#include <errno.h>
#include <string.h>
一個聲明
extern int errno;
四個重要函數(shù)
int ferror(FILE* stream);
int feof(FILE* stream);
char *strerror(int errnum);
void perror(const char *s);
以上是在錯誤處理中常用的操作,前兩者是必要包含的,最后的函數(shù)則是酌情使用
ferror:
0值,如果沒有錯誤則返回 0feof:
用于檢查是否到了文件尾,經(jīng)常用于文件的讀取工作,讀取到文件尾則返回非零值
input = fopen("file.in", "r");
while(!feof(input))
{
fscanf(input, "%s", str);
...
等同于
do{
rtn_value = fscanf(input, "%s", str);
...
}while(rtn_value != EOF);
strerror:
當某個函數(shù)或者操作觸發(fā)了設(shè)置 errno 變量的時候,我們可以立即使用該函數(shù)進行顯示輸出
strerror(errno);
輸出: Too many open files
perror:
與上方的函數(shù)相同,也是用來輸出錯誤的,只不過它自動使用 errno 變量,并且在自前方添加所傳入的參數(shù)以及一個冒號
perror("Now");
輸出: Now: Too many open files
同樣的,對于自己的錯誤處理,可以設(shè)計一個小體系來滿足自我需求
通過返回值
/* fun.h */
void fun_error(size_t errnum);
size_t test_fun(int arg);
在此我們可以讓外界接觸不到真實的包含有錯誤的數(shù)組或其他數(shù)據(jù)結(jié)構(gòu),而是將其放于.c文件中隱藏起來,通過一個函數(shù)來進行訪問。
隱藏錯誤實現(xiàn)
/* fun.c */
static const char * fun_err[] = { "Computing nagative!",
"Invalid argument",
"Bad result" };
size_t test_fun(int arg) { ... }
void fun_error(size_t errnum) { ... }
對于需要進一步規(guī)格化的設(shè)計來說,可以使用 enum 或者 #define 來設(shè)定每個錯誤返回值的名字
設(shè)定名字
/*fun.h*/
#define ERR_CMPUTING 0
#define ERR_INVARG 1
#define ERR_BADRLT 2
/* 或者 */
enum { ERR_COMPUTING = 0,
ERR_INVALIDARG,
ERR_BADRESULT };
如此我們便可以在函數(shù)中使用錯誤的名字代號,而不是去記下每個數(shù)字的含義。對此也可以不使用數(shù)組這個數(shù)據(jù)結(jié)構(gòu)來保存錯誤信息,而采用 switch 在代碼中實現(xiàn)錯誤的處理
switch錯誤選擇·
/*fun.c*/
/*
static const char * fun_err[] = { "Computing nagative!",
"Invalid argument",
"Bad result" };
*/
...
void fun_error(size_t errnum)
{
switch(errnum)
{
case ERR_CMPUTING /*ERR_COMPUTING*/:
fprintf(stderr, "...");
break;
case ERR_INVARG /*ERR_INVALIDARG*/:
fprintf(stderr, "...");
break;
...
default :
...
}
return;
}
如此做的好處便是,不再需要去安排數(shù)組的個數(shù),而是直接在代碼中展示。并且可以加上一些預處理,來實現(xiàn)開關(guān)錯誤顯示。
開關(guān)錯誤
/* fun.c */
...
void fun_error(size_t errnum)
{
#if !defined(NOT_DEBUG)
switch(errnum)
{
...
}
#endif
return;
}