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