首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言文件讀取核心:深度解析 EOF 與 feof() 正確用法及常見陷阱

     編輯:程式設計綜合問答

核心結論

feof() 只有在「嘗試讀取」動作發生並碰到文件結尾後才返回真。
**絕不可用 `while (!feof(fp))` 控制讀取迴圈** —— 會導致最後一行被重複處理。

錯誤示範與原因

// ❌ 錯誤模式
while (!feof(fp)) {
    fgets(buf, SIZE, fp);
    printf("%s", buf);  // 最後一行輸出兩次
}

執行流程:
1. 讀完最後一行後,文件指針恰好在 EOF,**但 feof() 仍為假**
2. 迴圈條件通過,進入下一次迭代
3. `fgets` 嘗試讀取,碰到 EOF 返回 NULL,**這時 feof() 才置真**
4. `buf` 內容未變 (仍是上一行),錯誤輸出第二次

正確模式 (三種等價寫法)

1. 直接用讀取函數返回值判斷 (最推薦)

// fgets 版
while (fgets(buf, SIZE, fp) != NULL) {
    printf("%s", buf);
}

// fread 版
while (fread(buf, 1, SIZE, fp) == SIZE) { /* 處理完整塊 */ }
// 最後一塊不足 SIZE 時需額外處理

// fscanf 版
while (fscanf(fp, "%d", &num) == 1) { /* 成功讀取 1 個整數 */ }

2. 讀取後立即檢查 feof() 中斷

while (true) {
    fgets(buf, SIZE, fp);
    if (feof(fp)) break;  // 讀取動作已發生,feof 可靠
    printf("%s", buf);
}

3. C++ 風格 (若編譯器支援)

std::ifstream fin("1.txt");
std::string line;
while (std::getline(fin, line)) { std::cout << line << '\n'; }

EOF 與 feof() 關係圖解

文件內容:  "12345\n\0"   (6 bytes + 隱含 EOF 標記)

fp->_ptr  讀取前 → 讀 '1' → ... → 讀 '\n' → 嘗試再讀 → 碰 EOF
fp->_flag  正常    正常      正常        _IOEOF 被置位
feof()    false   false     false       true
fgets()   "12345\n"  返回buf   返回buf     返回NULL

關鍵點總結

  • EOF 是宏常數 (-1),表示「無效字符」;feof() 是函數,檢查流的 _IOEOF 標志位。
  • 標志位**只有在讀寫操作嘗試越過文件末尾時**才被設置。
  • 二進制文件讀取同樣適用:while (fread(&item, sizeof(Item), 1, fp) == 1)。
  • 網絡流/管道無 EOF 概念,只能依賴返回值 (0 表關閉,-1 表錯誤)。

參考資源

CSDN 專欄:C語言文件操作 EOF 與 feof 詳細解析

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