標准I/O庫處理很多細節,使得便於用戶使用。
流和 FILE 對象
對於標准I/O庫,操作是圍繞 流(stream)進行的。當用標准I/O打開或創建一個文件時,我們已使一個流與一個文件相關聯。
對於ASCII字符集,一個字符用一個字節表示。對於國際字符集,一個字符可用多個字節表示。流的定向決定所讀,寫的字符是單字節還是多字節。
一個流在創建的最初,並沒有定向,如果對未定向的流使用多字節I/O函數,則將該流定向為款定向的,反之如果使用單字節I/O函數,則將流的定向設為字節定向的。
改變流的定向的函數(只有兩個):
freopen : 清楚一個流的定向
fwide : 設置流的定向
int fwide ( FILE *fp , int mode );
寬定向返回正值,字節定向返回負值,未定向的返回0;
fwide 並不改變已定向流的定向。
標准輸入 , 標准輸出 , 標准錯誤。
文件描述符 分別為 STDIN_FILENO , STDOUT_FILENO , STDERR_FILENO
通過預定文件指針 stdin , stdout , stderr。這三個文件指針分別在頭文件<stdio.h>中
緩沖
標准I/O 庫提供緩沖的目的是盡可能減少使用 read 和 write 調用的次數。
標准I/O 提供了一下 3種類型的緩沖:
全緩沖:在填滿標准I/O緩沖區後才進行實際I/O操作。
行緩沖:在輸入和輸出遇到換行符時,標准I/O庫執行I/O操作。
不緩沖:比如strerr,這樣使得出錯信息可以盡快顯示出來。
對任何一個給定的流,可以調用下列兩個函數中的一個更改緩沖類型。
void setbuf ( FILE *restrict fp , char *restrict buf ) ;
int setvbuf ( FILE *restrict fp , char *restrict buf , int mode , size_t size );
使用 setbuf 函數打開或關閉緩沖機制。為了帶緩沖進行I/O,參數buf指向一個長度為BUFSIZE的緩沖區,為了關閉緩沖,將buf設置為NULL。
使用 setvbuf , 可以精確的說明所需緩沖類型。 mode 參數:
_IOFBF 全緩沖
_IOLBF 行緩沖
_IONBF 不緩沖
147頁有圖。
打開流
下列三個函數打開一個標准I/O流。
FILE *fopen ( const char *restrict pathname , const char *restrict type );
FILE *freopen ( const char *restrict pathname , const char *restrict type , FILE *restrict fp );
FILE *fdopen ( int fd , const char *type );
區別在於:
type有15種不同的值 —— 圖5.2
讀和寫流
輸入函數:
以下三個函數可以一次讀一個字符
int getc ( FILE *fp )
int fgetc (FILE *fp )
int getchar ( void )
getchar 等同於 getc(stdin)。
getc可被實現為宏,fgetc不能實現為宏。
由於不管出錯還是達到文件尾端。三個函數都是返回同樣的值。為了區分,調用ferror 或 feof
int ferror ( FILE *fp )
int feof ( FILE *fp )
在大多數實現中,為每個流在FILE對象中維護了兩個標志:
出錯標志
文件結束標志
輸出函數:
int putc ( int c , FILE *fp )
int fputc ( int c , FILE *fp )
int putchar ( int c )
putchar( C ) 等同於 putc ( c , stdout ) , putc 可被實現為宏 , 而fputc不能實現為宏。
每次一行 I/O
char *fgets ( char *restrict buf , int n , FILE *restrict fp )
char *gets ( char *buf )
gets從標准輸入讀, fgets 從指定的流讀。
對於 fgets , 必須指定緩沖的長度為 n 。 此函數一直讀到下一個換行符為止。
gets是一個不推薦使用的函數,因為不能指定在使用gets時緩沖區的長度。可能造成緩沖區溢出。
gets並不將換行符存入緩沖區
fputs 和 puts 提供每次輸出一行的功能
int fputs ( const char *restrict str , FILE *restrict fp )
int puts ( const char *str )
函數 fputs 將一個以 null 字節終止的字符串寫到指定的流,尾端的null不寫出。
函數 puts 將一個以 null 字節終止的字符串寫到標准輸出,終止符不寫出。但隨後將一個換行符寫到標准輸出。
應當盡量使用 fgtes 和 fputs。
標准 I/O 的效率
二進制 I/O
以下兩個函數用於執行二進制 I/O 操作
size_t fread ( void *restrict ptr , size_t size , size_t nobj , FILE *restrict fp );
size_t fwrite ( const void *restrict ptr , size_t size , size_t nobj , FILE *restrict fp );