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` 內容未變 (仍是上一行),錯誤輸出第二次
// 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 個整數 */ }
while (true) {
fgets(buf, SIZE, fp);
if (feof(fp)) break; // 讀取動作已發生,feof 可靠
printf("%s", buf);
}
std::ifstream fin("1.txt");
std::string line;
while (std::getline(fin, line)) { std::cout << line << '\n'; }
文件內容: "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
while (fread(&item, sizeof(Item), 1, fp) == 1)。