可以編寫一個用來調試的函數error。如果調試信息是送往屏幕,編寫方法與前面定義的DEBUG函數是一樣的,只是有人喜歡使用error做名字,有人喜歡用DEBUG做名字。
考慮到用戶有可能把輸出定向到某個文件,這就可能造成將程序所產生的錯誤信息也會按定向指定文件,顯然這不是所希望的結果。上面定義的DEBUG函數就會發生這種情況,而這裡定義error函數就增加了新的措施,從而避免發生這種情況。
利用標準庫提供的標準錯誤流stderr,就可以解決這個問題。送到標準錯誤流的信息不受輸入流重定向的影響,因此也就不會混入定向的文件中。即使標準輸出流被定向,送到stdeer的信息仍會顯示在電腦屏幕上。
這裡需要用到一個新的庫函數vfprintf,這個函數的原型如下:
int vfprintf (FILE *stream , char *format , va_list param );
功能:將格式化的數據輸出到指定的數據流中。
函數說明:vfprintf會根據參數format字符串來轉換並格式化數據,然後將結果輸出到參數stream指定的文件中,直到出現字符串結束符(『\0』)為止。關於參數format字符串的格式可參考printf函數。
返回值:成功則返回實際輸出的字符數,失敗則返回-1,錯誤原因存於errno中。
把stderr作為第一個參數即可達到要求。同理,使用fprintf時,也用stderr作為第一個參數。
error函數增加幾條輸出信息,突出的是error函數的輸出以及輸出的字符數。下面給出這個函數的定義。
#include<stdarg.h> void error (const char *format , ... ) { int num ; va_list ap ; va_start (ap , format ); fprintf (stderr , \"error :n\" ); // 標記為error 函數輸出 num=vfprintf (stderr ,format , ap ); va_end (ap ); fprintf (stderr , \"num = %dn\" , num ); // 輸出打印字數 }
下面是使用與例13.4一樣的主程序,演示使用error函數的例子。
【例13.9】使用自己定義的error函數的例子。
#include<stdio.h> // 將error 函數的定義拷貝到此處 // 主程序 int main (void ) { int data[3][3] , *p ; int sum=0 , i=0 , j=0 ; p=&data[0][0] ; for ( i=0 ; i<9 ; i++ ) * (p+i )=10+i ; for ( i=0 ; i<3 ; i++ ) { for ( j=0 ; j<3 ; j++ ) { sum = sum + data[i][j] ; error ( \"date[%d][%d] = %d \" , i , j ,data[i][j] ); } printf (\"n\" ); } printf (\"sum = %dn\" , sum ); return 0 ; }
將下面的輸出結果與例13.4對照,顯然只是多一些信息而已。
error : date[0][0] = 10 num = 16 error : date[0][1] = 11 num = 16 error : date[0][2] = 12 num = 16 error : date[1][0] = 13 num = 16 error : date[1][1] = 14 num = 16 error : date[1][2] = 15 num = 16 error : date[2][0] = 16 num = 16 error : date[2][1] = 17 num = 16 error : date[2][2] = 18 num = 16 sum = 126
可以為error函數增加一個參數,將原型聲明為如下形式:
void error ( int n , const char *format , …)
定義一個整型全局常量on_off,當它為0時,error函數不起作用(與空語句等效),當它為非0值時,error函數有效。下面的例子中,定義為0,即
const int on_off = 0 ;
【例13.10】為error函數增加開關的例子。
#include<stdio.h> #include<stdarg.h> void error (int on_of , const char *format , …) { int num ; if (on_of != 0 ) // 判斷是否使用error 函數 { //on_of 等於零時不使用error 函數,非零則使用 va_list ap ; va_start (ap , format ); fprintf (stderr , \"error :n\" ); // 標記為error 函數輸出 num=vfprintf (stderr ,format , ap ); va_end (ap ); fprintf (stderr , \"num = %dn\" , num ); // 輸出打印字數 } } int main (void ) { int data[3][3] , *p ; int sum=0 , i=0 , j=0 ; const int on_of = 0 ; // 非0 時開關有效 p=&data[0][0] ; for ( i=0 ; i<9 ; i++ ) * (p+i )=10+i ; for ( i=0 ; i<3 ; i++ ) { for ( j=0 ; j<3 ; j++ ) { sum = sum + data[i][j] ; error (on_of , \"date[%d][%d] = %d \" , i , j ,data[i][j] ); } error (on_of , \"n\" ); } printf (\"sum = %dn\" , sum ); return 0 ; }
on_off為零,程序輸出結果為:
sum = 126
on_off非零時,程序輸出結果與例13.9的結果一樣。