核心類型與指標
FILE *fp; // FILE 是不透明結構體,fp 為檔案流指標
// 內部封裝:檔案描述符、緩衝區指標/大小、位置指標、錯誤/EOF 標記、鎖等
三大操作階段
| 階段 | 底層 (Unix/POSIX) | 標準庫 (帶緩衝) | 關鍵差異 |
| 開啟 | open() → 返回 int fd | fopen() → 返回 FILE* | 標準庫分配緩衝區 (預設 4KB/8KB),行/全緩衝模式 |
| 讀寫 | read()/write() | fread()/fwrite()/fgets()/fputs() | 標準庫操作緩衝區,批量落盤,減少系統調用 |
| 關閉 | close() | fclose() | 標準庫**刷新緩衝區**再關閉 fd,防止資料遺失 |
關鍵函數逐行解析
int ReadDat(void) {
FILE *fp;
int i = 0;
char *p;
extern char xx[][80]; // 假設外部定義
// 1. 開檔:失敗返回 NULL,錯誤碼在 errno
if ((fp = fopen("IN.DAT", "r")) == NULL) return 1;
// 2. 逐行讀取:fgets 讀取至 \n 或 size-1 或 EOF
while (fgets(xx[i], 80, fp) != NULL) {
// 3. 尋找換行符:strchr 返回首次出現位址,否則 NULL
p = strchr(xx[i], '\n');
if (p) *p = '\0'; // 將 \n 替換為字串結束符
i++;
}
// 隱含:迴圈結束後應 fclose(fp);
return 0;
}
strchr 詳細行為
- 原型:
char *strchr(const char *s, int c);
- 在
s 中尋找 **首個** 與 (char)c 相等的字符。
- **包含結束符 \0** 在搜尋範圍內:
strchr(s, '\0') 返回指向 \0 的指標。
- 返回:找到 → 指向該字符的指標;未找到 →
NULL。
常見錯誤與最佳實踐
- 忘記
fclose:導致緩衝區未刷新、檔案描述符洩漏、鎖定檔案。
→ **RAII 風格**:FILE *fp = fopen(...); if(fp){ ... fclose(fp); }
- 緩衝區溢出:
fgets(buf, sizeof(buf), fp) 必須傳 sizeof(buf),而非硬編碼常數。
- 二進制模式:讀寫結構體/圖片需
"rb"/"wb",避免 Windows \r\n 轉換破壞數據。
- 錯誤處理:
ferror(fp) 檢測讀寫錯誤,feof(fp) 檢測 EOF,clearerr(fp) 重置標記。
進階:自定義緩衝區
char mybuf[8192];
setvbuf(fp, mybuf, _IOFBF, sizeof(mybuf)); // 全緩衝,大緩衝區提升大檔順序讀寫效能