標籤:c 指標 io
第十五章 輸入輸出函數
這一章讀完的第一感覺就是“呵呵”。
如果說上過C語言課,基本上scanf()/printf()算是用的比較熟練了。尤其是那些抽象的格式說明。還有scanf()為什麼要加括弧。
讀過本書前面的內容的話,getchar(),putchar(),gets(),puts()這些應該也問題不大。
再如果的話,你學過電腦圖形學,你玩過OpenGL,聽說過雙緩衝機制,那麼fflush()也肯定弄明白了。
再加上FILE的操作,輸入輸出定位重新整理刪除改名,流的概念。
這一章就會把這些串起來講。內容非常的多,我讀的也是走馬觀花的感覺。
總結:
perror(char const *message);和exit(int status);這兩條語句前者是產生一個錯誤報表。後者就比較重要,後者會終止程式。預定義符號EXIT_SUCCESS和EXIT_FAILURE分別提示程式的終止是成功還是失敗。
所有的I/O的庫函數都在stdio.h裡面。I/O介面都是流,文字資料流,二進位流。
FILE是一種資料結構,管理緩衝區和儲存流的狀態。包括標準輸入、標準輸出和標準錯誤。
對檔案操作:先用fopen()函數開啟檔案,返回一個指向FILE結構的指標,這個FILE結構指派給進行操作的流進行操作,指標類型必需為FILE *。有一些參數的模式,你可以指定它為二進位流還是文字資料流傳輸。在檔案結束的時候用fclose()來關閉。
這裡面有許許多多的I/O函數,其實都是有一些微小的差別,本質上執行相同的任務。
對字元操作:getchar(),putchar()為逐個字元的實現,只從標準輸入讀取。fgetc(),getc()都接受一個流參數。fputc(),putc(),putchar()具有和對應的輸入函數相同的屬性。ungetc()用於把一個不需要的字元退回到流中,用的不多。
對行操作:既可以是格式化的,也可以是未格式化的。gets和puts函數家族執行未格式化的行I/O。fgets和gets都從一個指定的緩衝區中讀取一行,前者包括一個流參數,後者從標準輸入讀取。fgets函數更為安全,因為它包含一個緩衝區的長度參數,一旦超過這個長度值命令就會停止操作,但是gets這麼看就像個玩具,它會一直一直讀緩衝區,溢出也完全停不下來。fputs和puts函數把文本寫入到流中。gets將去除它所讀取的行分行符號,puts函數在寫入到緩衝區的文本後面加上一個分行符號。
scanf和printf函數也執行格式化的I/O操作。
scanf從標準輸入讀取,fscanf接受一個流參數,sscanf從一個記憶體中的緩衝區接受字元。
printf跟以上一樣。
對二進位流操作:比使用字元的效率更高,fread和fwrite是函數執行二進位I/O操作。均包含四個參數:指向緩衝區的指標,緩衝區每個元素的長度、需要讀寫的元素個數以及需要操作的流。
警告:
1、不檢查fopen函數的返回值。
你應該是種檢查fopen函數的返回值!如果函數失敗,它會返回一個NULL值。如果程式不檢查錯誤,這個NULL指標就會傳給後續的I/O函數。它們將對這個指標執行間接訪問,並將失敗。
FILE *input;
input = fopen("data3", "r");
if(input == NULL)
{
perror("data3");
exit(EXIT_FAILURE);
}
首先,fopen函數被調用,這個被開啟的檔案名稱叫data3,開啟用於讀取。然後對返回值進行檢查。
如果錯誤就會: data3:No such file or directory
2、改變檔案的位置將丟棄任何被退回到流的字元。
3、在使用fgets時指定太小的緩衝區。
fgets指定太小的緩衝區的話,會遺失資料。
4、使用gets的輸入溢出緩衝區且沒有被檢測到。
gets是不會檢測溢出的,而溢出的後果你懂得。
5、使用任何scanf系列函數時,格式代碼和參數指標類型不符。
scanf相當於你把一個參數通過指標傳遞給函數,所以參數的指標必須對。
6、在任何scanf系列函數的每個非數組、非指標參數前往了加上&符號。
7、sprintf函數的輸入溢出了緩衝區且未被檢測到。
見上!
8、混淆printf和scanf格式代碼。
9、在有些長整數長於普通整數的機器上列印長整數值時,忘了在格式代碼中指定l修訂符。
10、使用自動數組作為流的緩衝區時應該多加小心。
編程提示:
1、在可能出現錯誤的場合,檢查並報告錯誤。
這個提示其實意義不大,錯誤報表很難記下來。起碼是現階段。
2、操作文本行而無需顧及它們的外部表格示形式這個能力有助於提高程式的可移植性。
3、使用scanf限定符提高可移植性。
4、當你列印長整數時,即使你所使用的機器並不重要,堅持使用l修改符可以提高可移植性。