C語言實戰105例--1一個價值三天的BUG
本系列筆記是參考《C語言實戰105例》及程式碼的學習筆記。
本節是使用sscanf函式處理行定向的輸入。程式為實現輸入兩個整數求和的功能。
注意:1、指標引數的型別必須是對應格式的程式碼的正確型別
2、正確使用限定符(指定引數的長度)
程式碼如下:
#include<stdio.h> #include<stdlib.h> #define BUFFERSIZE 1024 /*允許處理的最長行有1024個字元*/ int main() { int a,b,sum; /*將輸入的兩個數分別儲存在變數a和b中,sum=a+b*/ char buffer[BUFFERSIZE]; printf("***********************************\n"); printf("* Welcome to use our counter *\n"); printf("* Input two integers in one line *\n"); printf("* The sum will be printed *\n"); printf("* Input the char '#' to quit *\n"); printf("***********************************\n"); /*從標準輸入(stdin)讀取輸入的資料,儲存在buffer中. 如果讀取的第一個字元是'#'則推出程式*/ while((fgets(buffer,BUFFERSIZE,stdin)!=NULL)&&(buffer[0]!='#')) { if(sscanf(buffer,"%d %d",&a,&b)!=2) /*處理儲存在buffer中的一行資料*/ { printf("The input is skipped:%s",buffer);/*如果輸入的數字不是兩個則報錯*/ continue; /*繼續讀取下一組資料*/ } sum=a+b; /*計算a與b的和*/ printf("The sum of %d and %d is %d\n",a,b,sum); /*輸出計算結果*/ } return 0; }
其中我不懂的地方:
1、buffer--它一般用來定義陣列,因為它本身的意思就是“緩衝區”,在C語言裡,陣列就是個緩衝區,所以用常常用它。
2、fgets函式
- 函式原型是:char *fgets(char *s, int n, FILE *stream);
從檔案結構體指標stream中讀取資料,每次讀取一行。讀取的資料儲存在buf指向的字元陣列中,每次最多讀取bufsize-1個字元(第bufsize個字元賦'\0'),如果檔案中的該行,不足bufsize-1個字元,則讀完該行就結束。
如若該行(包括最後一個換行符)的字元數超過bufsize-1,則fgets只返回一個不完整的行,但是,緩衝區總是以
函式成功將返回buf,失敗或讀到檔案結尾返回NULL。因此我們不能直接通過fgets的返回值來判斷函式是否是出錯而終止的,應該藉助feof函式或者ferror函式來判斷。
- 與gets相比使用這個好處是:讀取指定大小的資料,避免gets函式從stdin接收字串而不檢查它所複製的快取的容積導致的快取溢位問題。
- 功能:
1、《UNIX 環境高階程式設計》中指出,每次呼叫fgets函式會造成標準輸出裝置自動刷清!案例詳見《UNIX環境高階程式設計(第二版)》中程式清單1-5和課後習題5.7,習題5.7的答案中給出了相關的論述。
2、初入門者,大多數是在WINDOWS下,使用VS進行練習的。此環境下,對注意1中的情況進行測試,並不能看到案例中所描述的情景,因為具體的實現不同。
stream檔案流指標體指向檔案內容地址的偏移原則
例:
如果一個檔案的當前位置的文字如下
Love, I Have
Since you can do it.
如果用fgets(str1,6,file1);去讀取
則執行後str1 = "Love," ,讀取了6-1=5個字元
這個時候再執行fgets(str1,20,file1)則執行後str1 = " I Have\n"
而如果
fgets(str1,23,file1);
則執行str1="Love ,I Have",讀取了一行(包括行尾的'\n',並自動加上字串結束符'\0'),當前檔案位置移至下一行,雖 然23大於當前行上字元總和,可是不會繼續到下一行。而下一次呼叫fgets()繼續讀取的時候是從下一行開始讀。