首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言 EOF 與 feof() 深度解析:為什麼二進制檔案不能用 EOF 判斷結束

     編輯:關於C語言

EOF (End Of File) 的本質

  • 定義於 <stdio.h>,通常展開為 -1(int 型別)。
  • **僅適用於文本檔案**的讀取迴圈終止條件。

文本檔案為何可用 EOF?

文本模式下,資料以 ASCII 字元碼(0~255)儲存。**文本流中不可能出現 -1**,因此 getc()、fgetc() 返回 EOF (-1) 可唯一標識「檔案結束」或「讀取錯誤」。

二進制檔案的陷阱

二進制模式下,資料按原始位元組儲存,**位元組值 0xFF (255) 合法存在**。若讀取函數返回 int,0xFF 擴展為 255,與 EOF (-1) 不衝突;但若直接將返回值賦給 char(有號),0xFF 會變成 -1,**誤判為 EOF**,導致提前終止讀取。

feof():通用的檔案結束檢測

ANSI C 提供 int feof(FILE *fp):

  • 返回 非零:檔案位置指標已到達檔案結束。
  • 返回 0:未到達結束。

適用於文本與二進制檔案。

正確讀取迴圈模式

// 文本檔案:可用 EOF 或 feof
while ((ch = fgetc(fp)) != EOF) { ... }

// 二進制檔案:必須用 feof 搭配返回值檢查
while (1) {
    size_t n = fread(buf, 1, sizeof(buf), fp);
    if (n == 0) {
        if (feof(fp)) break;      // 正常結束
        if (ferror(fp)) handle(); // 錯誤
    }
    process(buf, n);
}

// 通用模式(推薦):檢查讀取函數返回值,再用 feof/ferror 區分原因
int ch;
while ((ch = fgetc(fp)) != EOF) { ... }
if (feof(fp)) puts("正常讀完");
else if (ferror(fp)) perror("讀取錯誤");

常見誤區:feof() 在讀取**前**調用

// 錯誤!feof() 只在「嘗試讀取越界後」才置位
while (!feof(fp)) {
    fread(...); // 最後一次讀完後 feof 仍為 0,再進迴圈一次 → 處理垃圾數據
}

鐵律: 先嘗試讀取,根據返回值判斷是否成功,**失敗後**再用 feof()/ferror() 區分原因。

總結對照表

場景判斷結束方式備註
文本檔案逐字元讀取fgetc() == EOF 或 feof()EOF 為 -1,文本流無衝突
文本檔案逐行讀取fgets() == NULL返回 NULL 表示結束或錯誤
二進制檔案塊讀取fread() 返回值 < 要求數 + feof()/ferror()**絕不可**直接用 EOF
二進制檔案逐位元組fgetc() == EOF + 檢查 feof()需確保變數為 int 而非 char

牢記:「EOF 是文本流的約定俗成,feof() 才是檔案系統的官方標誌。」二進制處理永遠以「讀取函數返回值」為準,輔以 feof/ferror 診斷。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved