C標準庫提供三組成對的文件讀寫函數,分別面向格式化文本、行文本、二進制塊。本文系統對比其原型、行為差異、適用場景,並給出結構體數組讀寫實戰模式。
fscanf / fprintffscanf —— 從文本文件按格式讀取int fscanf(FILE *fp, const char *format, ...); // 示例:讀兩個整數 fscanf(fp, "%d%d", &a, &b);
scanf 類似,但輸入源為文件指針 fp。fscanf(stdin, ...) 等價於 scanf(...)。EOF。fprintf —— 按格式寫入文本文件int fprintf(FILE *fp, const char *format, ...); // 示例:寫兩個整數 fprintf(fp, "%d %d", x, y);
printf 類似,輸出目標為文件。fscanf 正確解析;避免輸出額外標籤字符(如 "x=")。fprintf(stdout, ...) 等價於 printf(...)。fgets / fputsfgets —— 讀取一行(含換行符)char *fgets(char *str, int n, FILE *fp);
n-1 字符,遇 \n 或 EOF 停止。\0。str(成功)或 NULL(EOF/出錯)。fputs —— 寫入字符串(不自動換行)int fputs(const char *str, FILE *fp);
str 直到 \0(不寫入 \0),不自動加 \n。\n,或用 fprintf(fp, "%s\n", str)。EOF(失敗)。fread / fwritesize_t fread(void *buffer, size_t size, size_t count, FILE *fp); size_t fwrite(const void *buffer, size_t size, size_t count, FILE *fp);
buffer:內存緩衝區地址(讀入目標 / 寫出源)。size:單個數據項字節數(如 sizeof(struct St))。count:項數。size * count,文件指針自動後移。count 或更少)。"rb"/"wb"/"rb+"),否則 Windows 下換行符轉換會損壞數據。struct St { char num[8]; float mk[5]; } pers[30];
// 寫入:逐個元素寫入(或一次性 fwrite(pers, sizeof(pers), 1, fp))
for(int i=0; i<30; i++)
fwrite(&pers[i], sizeof(struct St), 1, fp);
// 讀取:利用 feof 判斷結束
int i = 0;
fread(&pers[i], sizeof(struct St), 1, fp);
while(!feof(fp)) {
i++;
fread(&pers[i], sizeof(struct St), 1, fp);
}
優勢: 保持內存佈局原貌,讀寫速度快,無格式轉換開銷,適合大數據量、結構體、圖像/音頻原始數據。
| 場景 | 推薦函數 | 關鍵注意 |
|---|---|---|
| 配置文件、CSV、人類可讀文本 | fscanf/fprintf | 空格分隔、格式字符串匹配 |
| 逐行處理文本、日志、未知長度行 | fgets/fputs | 保留\n、手動加\n、緩衝區大小 |
| 結構體數組、圖像數據、高性能持久化 | fread/fwrite | 二進制模式、結構體對齊、跨平台端序 |
fgets 讀到 \n 會保留,處理前需手動去除(str[strcspn(str,"\n")]=0)。fputs 不換行,連續寫入必須手動加 \n。fscanf 遇不匹配格式會停留在當前位置,導致死循環,需檢查返回值並清理輸入緩衝。fopen 失敗返回 NULL,讀寫函數返回項數 < 期望值 即為錯誤/EOF。掌握 fscanf/fprintf(格式化)、fgets/fputs(行文本)、fread/fwrite(二進制塊)三組函數的語義邊界與最佳實踐,是C語言文件處理的核心技能。根據數據性質(文本/二進制)、訪問模式(隨機/流式)、性能要求選擇合適組合,並始終遵循「檢查返回值、二進制模式、緩衝區邊界」三大鐵律。