標準I/O基礎概念
標準I/O(Standard Input/Output)是C語言提供的一組高級文件操作函數,位于<stdio.h>頭文件中。與低級I/O(如Unix的系統調用read/write)相比,標準I/O引入了緩沖機制,能顯著提升讀寫效率。核心概念包括:
- 文件指針(FILE)*:指向FILE結構的指針,用于標識打開的文件流
- 緩沖類型:全緩沖、行緩沖、無緩沖
- 文本流與二進制流:文本流會處理換行符轉換,二進制流直接讀寫原始數據
文件打開與關閉
fopen函數
FILE *fopen(const char *filename, const char *mode);
參數:
filename
:文件路徑字符串mode
:打開模式:"r"
:只讀(文件必須存在)"w"
:只寫(創建新文件或清空已有文件)"a"
:追加(在文件末尾寫入)"r+"
:讀寫(文件必須存在)"w+"
:讀寫(創建新文件或清空已有文件)"a+"
:讀寫(從文件末尾開始)- 附加
b
表示二進制模式(如"rb"
)
返回值:成功返回FILE指針,失敗返回NULL
fclose函數
int fclose(FILE *stream);
- 參數:要關閉的文件流指針
- 返回值:成功返回0,失敗返回EOF
- 注意:關閉前會刷新緩沖區,多次關閉同一流會導致未定義行為
字符I/O操作
fgetc函數
int fgetc(FILE *stream);
- 從指定流讀取一個字符
- 返回值:成功返回讀取的字符(轉為unsigned char再轉int),失敗或到達文件尾返回EOF
fputc函數
int fputc(int c, FILE *stream);
- 向指定流寫入一個字符
- 參數:
c
會被轉為unsigned char寫入 - 返回值:成功返回寫入的字符,失敗返回EOF
使用示例:
// 文件復制示例
FILE *src = fopen("input.txt", "r");
FILE *dst = fopen("output.txt", "w");
int ch;
while ((ch = fgetc(src)) != EOF) {fputc(ch, dst);
}
fclose(src);
fclose(dst);
行I/O操作
fgets函數
char *fgets(char *str, int n, FILE *stream);
- 從流中讀取最多n-1個字符到str緩沖區
- 遇到換行符或EOF時停止,換行符會被保留
- 緩沖區末尾自動添加'\0'
- 返回值:成功返回str指針,失敗或到達文件尾返回NULL
fputs函數
int fputs(const char *str, FILE *stream);
- 將字符串寫入流,不包含結尾的'\0'
- 返回值:成功返回非負值,失敗返回EOF
使用示例:
// 行計數示例
FILE *fp = fopen("file.txt", "r");
char buffer[256];
int lines = 0;
while (fgets(buffer, sizeof(buffer), fp)) {lines++;
}
fclose(fp);
格式化I/O操作
fscanf函數
int fscanf(FILE *stream, const char *format, ...);
- 從流中按指定格式讀取數據
- 格式字符串與scanf相同
- 返回值:成功匹配并賦值的參數個數,失敗或到達文件尾返回EOF
fprintf函數
int fprintf(FILE *stream, const char *format, ...);
- 按指定格式向流寫入數據
- 格式字符串與printf相同
- 返回值:成功寫入的字符數,失敗返回負值
使用示例:
// 結構化數據讀寫
typedef struct {int id;char name[50];float score;
} Student;FILE *fp = fopen("data.txt", "w+");
Student s = {1, "Alice", 95.5f};
fprintf(fp, "%d %s %f\n", s.id, s.name, s.score);rewind(fp);
Student new_s;
fscanf(fp, "%d %49s %f", &new_s.id, new_s.name, &new_s.score);
fclose(fp);
錯誤處理與狀態檢查
ferror:檢查流錯誤標志
int ferror(FILE *stream);
feof:檢查文件結束標志
int feof(FILE *stream);
clearerr:清除錯誤和EOF標志
void clearerr(FILE *stream);
正確使用模式:
while (1) {ch = fgetc(fp);if (feof(fp)) break;if (ferror(fp)) {perror("Read error");break;}// 處理字符
}