一旦打開了流,則可在三種不同類型的非格式化I/O中進行選擇,對其進行讀、寫操作:
(1)每次一個字符的I/O。一次讀或寫一個字符,如果流是帶緩沖的,則標準I/O會處理所有緩沖。
(2)每次一行的I/O。如果想要一次讀或寫一行,則使用fgets和fputs。每行都以一個換行符終止。當調用fgets時,應說明能處理的最大行長。
(3)直接I/O。fread和fwrite函數支持這種類型的I/O。每次I/O操作讀或寫某種數量的對象,而每個對象具有指定的長度。這兩個函數常用于從二進制文件中每次讀或寫一個結構。
直接I/O(direct I/O)這個術語來自ISO C標準,有時也被稱為二進制I/O、一次一個對象I/O、面向記錄的I/O或面向結構的I/O。
1、輸入函數
以下三個函數可用于一次讀一個字符。
#include <stdio.h>int getc( FILE *fp );int fgetc( FILE *fp );int getchar( void );三個函數的返回值:若成功則返回下一個字符,若已到達文件結尾或出錯則返回EOF
函數getchar等價于getc(stdin)。前兩個函數的區別是getc可被實現為宏,而fgetc則不能實現為宏。這意味著:
(1)getc的參數不應當是具有副作用的表達式。
(2)因為fgetc一定是一個函數,所以可以得到其地址。這就允許將fgetc的地址作為一個參數傳送給另一個函數。
(3)調用fgetc所需時間很可能長于調用getc,因為調用函數通常所需的時間長于調用宏。
這三個函數在返回下一個字符時,會將其unsigned char類型轉換為int類型。說明為不帶符號的理由是,如果最高位為1也不會使返回值為負。要求整型返回值的理由是,這樣就可以返回所有可能的字符再加上一個已出錯或已到達文件尾端的指示值。在<stdio.h>中的常量EOF被要求是一個負值,其值經常是-1。這就意味著不能將這三個函數的返回值存放在一個字符變量中,以后還要將這些函數的返回值與常量EOF相比較。
注意,不管是出錯還是到達文件尾端,這三個函數都返回同樣的值。為了區分這兩種不同的情況,必須調用ferror或feof。
#include <stdio.h>int ferror( FILE *fp );int feof( FILE *fp );兩個函數返回值:若條件為真則返回非0值(真),否則返回0(假)void clearerr( FILE *fp );
在大多數實現中,為每個流在FILE對象中維持了兩個標志:
調用clearerr則清除這兩個標志。
從流中讀取數據以后,可以調用ungetc將字符再壓送回流中。
#include <stdio.h>int ungetc( int c, FILE *fp );返回值:若成功則返回c,若出錯則返回EOF
壓送回流中的字符以后又可從流中讀出,但讀出的字符的順序與壓送回的順序相反。應當了解,雖然ISO C允許實現支持任意次數的回送,但是它要求實現提供一次只送回一個字符。我們不能期望一次能送回多個字符。
回送的字符不必一定是上一次讀到的字符。不能回送EOF,但是當已經達到文件尾端時,仍可以回送一個字符,下次讀將返回該字符,再次讀則返回EOF。之所以能這樣做的原因是一次成功的ungetc調用會清除該流的文件結束標志。???(這原因解釋的,越解釋越糊涂)
當正在讀一個輸入流,并進行某種形式的分字或分記號操作時,會經常用到回送字符操作。有時需要先看一看下一個字符,以決定如何處理當前字符。然后就需要方便地將剛查看的字符送回,以便下一次調用getc時返回該字符。如果標準I/O庫不提供回送能力,就需要將該字符存放到一個我們自己的變量中,并設置一個標志以便判別在下一次需要一個字符時是調用getc,還是從我們自己的變量中取用。
用ungetc壓送回字符時,并沒有將它們寫到文件中或設備上,只是將它們寫回標準I/O庫的流緩沖區中。
2、輸出函數
對應于上面所述的每個輸入函數都有一個輸出函數。
#include <stdio.h>int putc( int c, FILE *fp );int fputc( int c, FILE *fp );int putchar( int c );三個函數返回值:若成功則返回c,若出錯則返回EOF
與輸入函數一樣,putchar(c)等效于putc(c,staout),putc可實現為宏,而fputc則不能實現為宏。
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
新聞熱點
疑難解答