C++ 程式設計/程式碼/標準 C 庫/IO
標準 C 庫包含一些過時的例程,但由於 C++ 語言的歷史 以及保持相容性的目標,這些例程包含在軟體包中。
C I/O 呼叫仍然出現在舊程式碼中(不僅是 ANSI C 89,甚至舊的 C++ 程式碼)。它在今天的使用可能取決於許多因素,例如程式碼庫的年齡、專案複雜程度,甚至程式設計師的經驗。如果你精通 C,為什麼要使用你不熟悉的東西呢?在某些情況下,C 樣式的 I/O 例程優於它們的 C++ I/O 對應物,例如,它們更緊湊,並且可能足夠用於不需要類的簡單專案。
| 語法 |
#include <cstdio>
void clearerr( FILE *stream );
|
clearerr 函式重置給定流的錯誤標誌和 EOF 指示器。如果發生錯誤,你可以使用 perror() 或 strerror() 來找出實際發生的錯誤,或者從全域性變數 errno 中讀取錯誤。
| 語法 |
#include <cstdio>
int fclose( FILE *stream );
|
fclose() 函式關閉給定的檔案流,釋放與該流關聯的任何緩衝區。fclose() 在成功時返回 0,否則返回 EOF。
| 語法 |
#include <cstdio>
int feof( FILE *stream );
|
feof() 函式在遇到檔案結尾時返回 TRUE,否則返回 FALSE。
| 語法 |
#include <cstdio>
int ferror( FILE *stream );
|
ferror() 函式檢查流是否有錯誤,如果未發生錯誤,則返回零,如果發生錯誤,則返回非零值。在發生錯誤的情況下,使用 perror() 來確定發生了哪個錯誤。
| 語法 |
#include <cstdio>
int fflush( FILE *stream );
|
如果給定的檔案流是輸出流,則 fflush() 會將輸出緩衝區寫入檔案。如果給定的流是輸入型別,則 fflush() 的行為取決於使用的庫(例如,某些庫會忽略操作,其他庫會報告錯誤,而其他庫會清除待處理的輸入)。
fflush() 在除錯時非常有用(例如,如果程式在緩衝區傳送到螢幕之前發生段錯誤),或者它可以用於在長時間處理之前確保部分輸出顯示。
預設情況下,大多數實現都會在每行結束時傳輸 stdout 的緩衝區,而 stderr 則在每次輸出時都會重新整理。如果存在重定向或管道,則此行為會發生變化,在這種情況下,呼叫 fflush(stdout) 可以幫助維護輸出流。
printf( "Before first call\n" );
fflush( stdout );
shady_function();
printf( "Before second call\n" );
fflush( stdout );
dangerous_dereference();
| 語法 |
#include <cstdio>
int fgetc( FILE *stream );
|
fgetc() 函式從流中返回下一個字元,如果遇到檔案結尾或發生錯誤,則返回 EOF。
| 語法 |
#include <cstdio>
int fgetpos( FILE *stream, fpos_t *position );
|
fgetpos() 函式將給定檔案流的檔案位置指示器儲存到給定的位置變數中。位置變數的型別為 fpos_t(在 cstdio 中定義),是一個可以儲存 FILE 中所有可能位置的物件。fgetpos() 在成功時返回零,在失敗時返回非零值。
| 語法 |
#include <cstdio>
char *fgets( char *str, int num, FILE *stream );
|
fgets() 函式從給定檔案流中讀取最多 num - 1 個字元,並將它們轉儲到 str 中。fgets() 生成的字串始終以 null 結尾。fgets() 將在到達行尾時停止,在這種情況下,str 將包含該換行符。否則,fgets() 將在到達 num - 1 個字元或遇到 EOF 字元時停止。fgets() 在成功時返回 str,在錯誤時返回 NULL。
| 語法 |
#include <cstdio>
FILE *fopen( const char *fname, const char *mode );
|
fopen() 函式開啟由 fname 指定的檔案,並返回與該檔案關聯的流。如果出現錯誤,fopen() 返回 NULL。mode 用於確定如何處理檔案(即用於輸入、輸出等)。
mode 包含最多三個字元。第一個字元是 "r"、"w" 或 "a",它指示檔案是如何開啟的。為讀取開啟的檔案從檔案開頭開始允許輸入。對於寫入,檔案將被擦除。對於追加,檔案將被保留,寫入檔案將從末尾開始。第二個字元是 "b",是一個可選標誌,它以二進位制形式開啟檔案 - 省略任何來自不同文字格式的轉換。第三個字元 "+" 是一個可選標誌,它允許對檔案執行讀寫操作(但檔案本身以相同的方式開啟)。
| 模式 | 意義 | 模式 | 意義 |
|---|---|---|---|
| "r" | 以讀取模式開啟文字檔案 | "r+" | 以讀寫模式開啟文字檔案 |
| "w" | 以寫入模式建立文字檔案 | "w+" | 以讀寫模式建立文字檔案 |
| "a" | 追加到文字檔案 | "a+" | 以讀寫模式開啟文字檔案 |
| "rb" | 以讀取模式開啟二進位制檔案 | "rb+" | 以讀寫模式開啟二進位制檔案 |
| "wb" | 以寫入模式建立二進位制檔案 | "wb+" | 以讀寫模式建立二進位制檔案 |
| "ab" | 追加到二進位制檔案 | "ab+" | 以讀寫模式開啟二進位制檔案 |
一個例子
int ch;
FILE *input = fopen( "stuff", "r" );
ch = getc( input );
| 語法 |
#include <cstdio>
int fprintf( FILE *stream, const char *format, ... );
|
fprintf() 函式根據指定的格式將資訊(引數)傳送到 stream 指示的檔案。fprintf() 在格式方面與 printf() 一樣。fprintf() 的返回值是輸出的字元數,如果出現錯誤,則為負數。一個例子
char name[20] = "Mary";
FILE *out;
out = fopen( "output.txt", "w" );
if( out != NULL )
fprintf( out, "Hello %s\n", name );
| 語法 |
#include <cstdio>
int fputc( int ch, FILE *stream );
|
fputc() 函式將給定的字元 ch 寫入給定的輸出流。返回值是該字元,除非出現錯誤,在這種情況下返回值為 EOF。
| 語法 |
#include <cstdio>
int fputs( const char *str, FILE *stream );
|
fputs() 函式將 str 指向的字元陣列寫入給定的輸出流。返回值在成功時是非負的,在失敗時為 EOF。
| 語法 |
#include <cstdio>
int fread( void *buffer, size_t size, size_t num, FILE *stream );
|
fread() 函式讀取 num 個物件(每個物件大小為 size 位元組),並將它們放入 buffer 指向的陣列中。資料來自給定的輸入流。函式的返回值是讀取的項數。可以使用 feof() 或 ferror() 來確定是否出現錯誤。
| 語法 |
#include <cstdio>
FILE *freopen( const char *fname, const char *mode, FILE *stream );
|
freopen() 函式用於將現有的流重新分配到不同的檔案和模式。呼叫此函式後,給定的檔案流將引用 fname,並具有 mode 給定的訪問許可權。freopen() 的返回值是新的流,如果出現錯誤,則為 NULL。
fscanf
[edit | edit source]| 語法 |
#include <cstdio>
int fscanf( FILE *stream, const char *format, ... );
|
fscanf() 函式從給定的檔案流中讀取資料,其方式與 scanf() 完全相同。fscanf() 的返回值是實際分配值的變數數量,包括零,如果沒有任何匹配項。如果在第一次匹配之前出現讀取錯誤,則返回 **EOF**。
fseek
[edit | edit source]| 語法 |
#include <cstdio>
int fseek( FILE *stream, long offset, int origin );
|
fseek() 函式設定給定流的檔案位置資料。origin 值應該具有以下值之一(在 cstdio 中定義)
| 名稱 | 解釋 |
|---|---|
| SEEK_SET | 從檔案開頭開始查詢 |
| SEEK_CUR | 從當前位置開始查詢 |
| SEEK_END | 從檔案結尾開始查詢 |
fseek() 在成功時返回零,在失敗時返回非零值。可以使用 fseek() 移動到檔案之外,但不能移動到開頭之前。使用 fseek() 將清除與該流關聯的 EOF 標誌。
fsetpos
[edit | edit source]| 語法 |
#include <cstdio>
int fsetpos( FILE *stream, const fpos_t *position );
|
fsetpos() 函式將給定流的檔案位置指示器移動到位置物件指定的位置。fpos_t 在 cstdio 中定義。fsetpos() 的返回值在成功時為零,在失敗時為非零值。
ftell
[edit | edit source]| 語法 |
#include <cstdio>
long ftell( FILE *stream );
|
ftell() 函式返回流的當前檔案位置,如果出現錯誤則返回 -1。
fwrite
[edit | edit source]| 語法 |
#include <cstdio>
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
|
fwrite() 函式從陣列緩衝區寫入 count 個大小為 size 的物件到流。返回值是寫入的物件數量。
getc
[edit | edit source]| 語法 |
#include <cstdio>
int getc( FILE *stream );
|
getc() 函式從流中返回下一個字元,如果到達檔案末尾則返回 **EOF**。getc() 與 fgetc() 相同。例如
int ch;
FILE *input = fopen( "stuff", "r" );
ch = getc( input );
while( ch != EOF ) {
printf( "%c", ch );
ch = getc( input );
}
getchar
[edit | edit source]| 語法 |
#include <cstdio>
int getchar( void );
|
getchar() 函式從 **stdin** 返回下一個字元,如果到達檔案末尾則返回 **EOF**。
gets
[edit | edit source]| 語法 |
#include <cstdio>
char *gets( char *str );
|
gets() 函式從 stdin 讀取字元並將其載入到 str 中,直到遇到換行符或 **EOF**。換行符被轉換為 null 終止符。gets() 的返回值是讀取的字串,如果出現錯誤則為 **NULL**。
perror
[edit | edit source]| 語法 |
#include <cstdio>
void perror( const char *str );
|
perror() 函式將 str、一個 ":"、一個空格、一個與全域性變數 errno 相對應的實現定義和/或語言相關的錯誤訊息以及一個換行符寫入 stderr。例如
char* input_filename = "not_found.txt";
FILE* input = fopen( input_filename, "r" );
if( input == NULL ) {
char error_msg[255];
sprintf( error_msg, "Error opening file '%s'", input_filename );
perror( error_msg );
exit( -1 );
}
如果找不到名為 not_found.txt 的檔案,這段程式碼將生成以下輸出
Error opening file 'not_found.txt': No such file or directory
如果 "str" 是一個空指標或指向空位元組,則只將與 errno 相對應的錯誤訊息和一個換行符寫入 stderr。
printf
[edit | edit source]| 語法 |
#include <cstdio>
int printf( const char *format, ... );
cout<<printf;
|
printf() 函式根據傳遞給 printf() 的格式和其他引數將輸出列印到 **stdout**。格式字串由兩種型別的專案組成 - 將列印到螢幕上的字元,以及定義 printf() 的其他引數如何顯示的格式命令。基本上,您指定一個包含文字的格式字串,以及對映到 printf() 的其他引數的 "特殊" 字元。例如,這段程式碼
char name[20] = "Bob";
int age = 21;
printf( "Hello %s, you are %d years old\n", name, age );
顯示以下輸出
Hello Bob, you are 21 years old
%s 表示 "在適當位置插入第一個引數,一個字串"。%d 表示應該將第二個引數(一個整數)放置在那裡。有不同的 %-程式碼用於不同的變數型別,以及用於限制變數長度等的選項。
| 控制字元 | 解釋 |
|---|---|
| %c | 單個字元 |
| %d | 十進位制整數 |
| %i | 整數 |
| %e | 科學計數法,使用小寫 "e" |
| %E | 科學計數法,使用大寫 "E" |
| %f | 浮點數 |
| %g | 使用 %e 或 %f,以較短者為準 |
| %G | 使用 %E 或 %f,以較短者為準 |
| %o | 八進位制數 |
| %x | unsigned 十六進位制數,使用小寫字母 |
| %X | unsigned 十六進位制,使用大寫字母 |
| %u | 一個 unsigned 整數 |
| %s | 一個字串 |
| %ls | 一個寬字串 |
| %x | 一個十六進位制數 |
| %p | 一個指標 |
| %n | 引數應該是一個指向整數的指標,該整數用於儲存到目前為止寫入的字元數 |
| %% | 一個百分號 |
欄位長度說明符可以出現在最終控制字元之前,用於指示欄位的寬度
- h,當插入到 %d 中時,會導致引數成為一個短整型。
- l,當插入到 %d 中時,會導致引數成為一個長整型。
- l,當插入到 %f 中時,會導致引數成為一個雙精度浮點數。
- L,當插入到 %d 或 %f 中時,會導致引數分別成為一個長長整型或長雙精度浮點數。
在 % 符號和格式命令之間放置的整數充當最小欄位寬度說明符,並使用空格或零填充輸出,使其足夠長。如果要使用零填充,請在最小欄位寬度說明符之前放置一個零
%012d
您還可以包含精度修飾符,形式為 .N,其中 N 是某個數字,位於格式命令之前
%012.4d
精度修飾符根據使用的格式命令具有不同的含義
- 對於 %e、%E 和 %f,精度修飾符允許您指定所需的十進位制位數。例如,%12.6f 將顯示一個至少 12 位寬的浮點數,具有六位小數。
- 對於 %g 和 %G,精度修飾符決定顯示的有效數字的最大數量。
- 對於 %s,精度修飾符只是一個最大欄位長度,用於補充在句點之前的最小欄位長度。
所有 printf() 的輸出都是右對齊的,除非您在 % 符號後立即放置一個減號。例如,
%-12.4f
將顯示一個浮點數,最小為 12 個字元,4 位小數,並左對齊。您可以使用字母 l 和字母 h 修改 %d、%i、%o、%u 和 %x 型別說明符以指定長資料型別和短資料型別(例如 %hd 表示短整型)。%e、%f 和 %g 型別說明符可以在它們之前具有字母 l 以指示後面跟著一個雙精度浮點數。%g、%f 和 %e 型別說明符可以在前面加上字元 '#' 以確保即使沒有小數位也會顯示小數點。在 %x 型別說明符中使用 '#' 字元表示應使用 '0x' 字首列印十六進位制數。在 %o 型別說明符中使用 '#' 字元表示應使用 0 字首顯示八進位制值。
在型別說明符中插入加號 '+' 將強制正值以 '+' 符號開頭。在其中放置一個空格字元 ' ' 將強制正值以單個空格字元開頭。
您還可以包含輸出字串中的常量轉義序列。
printf() 的返回值是列印的字元數,如果發生錯誤,則為負數。
putc
[edit | edit source]| 語法 |
#include <cstdio>
int putc( int ch, FILE *stream );
|
putc() 函式將字元 ch 寫入流。返回值是寫入的字元,或者如果出現錯誤則為 EOF。例如
int ch;
FILE *input, *output;
input = fopen( "tmp.c", "r" );
output = fopen( "tmpCopy.c", "w" );
ch = getc( input );
while( ch != EOF ) {
putc( ch, output );
ch = getc( input );
}
fclose( input );
fclose( output );
生成名為 tmpCopy.c 的檔案 tmp.c 的副本。
putchar
[edit | edit source]| 語法 |
#include <cstdio>
int putchar( int ch );
|
putchar() 函式將 ch 寫入 stdout。程式碼
putchar( ch );
與
putc( ch, stdout );
相同。putchar() 的返回值是寫入的字元,或者如果出現錯誤則為 EOF。
- 相關主題
- putc
puts
[edit | edit source]| 語法 |
#include <cstdio>
int puts( char *str );
|
puts() 函式將 str 寫入 stdout。puts() 在成功時返回非負值,或者在失敗時返回 EOF。
remove
[edit | edit source]| 語法 |
#include <cstdio>
int remove( const char *fname );
|
remove() 函式擦除由 fname 指定的檔案。remove() 的返回值在成功時為零,如果出現錯誤則為非零。
- 相關主題
- rename
rename
[edit | edit source]| 語法 |
#include <cstdio>
int rename( const char *oldfname, const char *newfname );
|
rename() 函式將檔案 oldfname 的名稱更改為 newfname。rename() 的返回值在成功時為零,在錯誤時為非零。
- 相關主題
- remove
rewind
[edit | edit source]| 語法 |
#include <cstdio>
void rewind( FILE *stream );
|
rewind() 函式將檔案位置指示器移到指定流的開頭,還會清除與該流相關的錯誤和 EOF 標誌。
- 相關主題
- fseek
scanf
[edit | edit source]| 語法 |
#include <cstdio>
int scanf( const char *format, ... );
|
scanf() 函式根據給定的格式從 stdin 讀取輸入,並將資料儲存在其他引數中。它的工作原理與 printf() 非常類似。格式字串由控制字元、空格字元和非空格字元組成。控制字元以 % 符號開頭,如下所示
| 控制字元 | 解釋 |
|---|---|
| %c | 單個字元 |
| %d | 十進位制整數 |
| %i | 整數 |
| %e, %f, %g | 浮點數 |
| %lf | 一個雙精度浮點數 |
| %o | 八進位制數 |
| %s | 一個字串 |
| %x | 一個十六進位制數 |
| %p | 一個指標 |
| %n | 一個等於到目前為止讀取的字元數的整數 |
| %u | 一個 unsigned 整數 |
| %[] | 一組字元 |
| %% | 一個百分號 |
scanf() 讀取輸入,匹配來自 format 的字元。當讀取控制字元時,它將值放入下一個變數中。空格(製表符、空格等)將被跳過。非空格字元將與輸入匹配,然後丟棄。如果在 % 符號和控制字元之間有一個數字,那麼只有這麼多字元會被轉換為變數。如果 scanf() 遇到一組字元,由 %[] 控制字元表示,那麼括號內找到的任何字元都會被讀入變數。scanf() 的返回值是成功分配值的變數數,或者如果出現錯誤則為 EOF。
此程式碼段使用 scanf() 從使用者處讀取一個 int、一個 float 和一個 double。請注意,傳遞給 scanf() 的變數引數是按地址傳遞的,如每個變數之前的取地址符 (&) 所示
int i;
float f;
double d;
printf( "Enter an integer: " );
scanf( "%d", &i );
printf( "Enter a float: " );
scanf( "%f", &f );
printf( "Enter a double: " );
scanf( "%lf", &d );
printf( "You entered %d, %f, and %f\n", i, f, d );
setbuf
[edit | edit source]| 語法 |
#include <cstdio>
void setbuf( FILE *stream, char *buffer );
|
setbuf() 函式將流設定為使用 buffer,或者如果 buffer 為 NULL,則關閉緩衝。此函式預期緩衝區長度為 BUFSIZ 個字元 - 由於此函式不支援指定緩衝區大小,因此大於 BUFSIZ 的緩衝區將部分未被使用。
| 語法 |
#include <cstdio>
int setvbuf( FILE *stream, char *buffer, int mode, size_t size );
|
函式 setvbuf() 將stream的緩衝區設定為buffer,大小為size。mode可以是以下之一:
- _IOFBF,表示全緩衝
- _IOLBF,表示行緩衝
- _IONBF,表示不緩衝
| 語法 |
#include <cstdio>
int sprintf( char *buffer, const char *format, ... );
|
sprintf() 函式與 printf() 類似,區別在於輸出被髮送到buffer。返回值是寫入的字元數。例如
char string[50];
int file_number = 0;
sprintf( string, "file.%d", file_number );
file_number++;
output_file = fopen( string, "w" );
請注意,sprintf() 與 atoi() 這樣的函式作用相反 - atoi() 將字串轉換為數字,而 sprintf() 可以用於將數字轉換為字串。
例如,以下程式碼使用 sprintf() 將整數轉換為字元陣列
char result[100];
int num = 24;
sprintf( result, "%d", num );
這段程式碼類似,區別在於它將浮點數轉換為字元陣列
char result[100];
float fnum = 3.14159;
sprintf( result, "%f", fnum );
| 語法 |
#include <cstdio>
int sscanf( const char *buffer, const char *format, ... );
|
sscanf() 函式與 scanf() 類似,區別在於輸入從buffer讀取。
| 語法 |
#include <cstdio>
FILE *tmpfile( void );
|
tmpfile() 函式開啟一個具有唯一檔名的臨時檔案,並返回指向該檔案的指標。如果出錯,則返回 NULL。
- 相關主題
- tmpnam
| 語法 |
#include <cstdio>
char *tmpnam( char *name );
|
tmpnam() 函式建立一個唯一的檔名,並將它儲存在 name 中。tmpnam() 可以最多呼叫 TMP_MAX 次。
- 相關主題
- tmpfile
| 語法 |
#include <cstdio>
int ungetc( int ch, FILE *stream );
|
ungetc() 函式將字元ch放回stream。
| 語法 |
#include <cstdarg>
#include <cstdio>
int vprintf( char *format, va_list arg_ptr );
int vfprintf( FILE *stream, const char *format, va_list arg_ptr );
int vsprintf( char *buffer, char *format, va_list arg_ptr );
|
這些函式與 printf()、fprintf() 和 sprintf() 非常類似。區別在於引數列表是指向引數列表的指標。va_list 在 cstdarg 中定義,也由 (其他標準 C 函式) va_arg() 使用。
例如
void error( char *fmt, ... ) {
va_list args;
va_start( args, fmt );
fprintf( stderr, "Error: " );
vfprintf( stderr, fmt, args );
fprintf( stderr, "\n" );
va_end( args );
exit( 1 );
}