Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

深入理解 C 語言 EOF 與檔案結束判斷

編輯:Linux 教學

前言

許多 C 語言初學者對 EOF、getchar() 回傳值、feof() 與 ferror() 的關係存在誤解。本文釐清檔案結束判斷的正確邏輯,並詳細說明終端機下 Ctrl+D (Linux) / Ctrl+Z (Windows) 的行為差異。

1. EOF 的本質

  • EOF 是 <stdio.h> 定義的巨集常數,值通常為 -1(int 型別)。
  • 檔案資料流中並無實體「EOF 字元」。當讀取函數(如 getc、fgetc、getchar)無法讀取資料時,回傳 EOF。
  • 造成回傳 EOF 的兩種情況:
    1. 檔案已讀完(正常結束)。
    2. 讀取發生錯誤(如硬體故障、權限問題)。

2. 為何需要 feof() 與 ferror()?

當 fgetc() 回傳 EOF 時,無法單憑回傳值區分「檔案結束」還是「讀取錯誤」。必須配合:

  • feof(FILE *fp):檢查流的 EOF 標誌是否被設定(僅在嘗試讀取超過檔案末尾時才會設定)。
  • ferror(FILE *fp):檢查流的 錯誤標誌是否被設定。

正確判斷模式:

int c;
while ((c = fgetc(fp)) != EOF) {
    /* 處理字元 c */
}
if (feof(fp)) {
    puts("正常讀取完畢");
} else if (ferror(fp)) {
    perror("讀取錯誤");
}

3. getchar() 必須用 int 接收

/* 錯誤寫法 */
char c;
c = getchar();  // 若 getchar() 回傳 EOF (-1),賦值給 char 會截斷/轉換,導致判斷失敗

/* 正確寫法 (K&R C 強調) */
int c;
c = getchar();  // int 能完整容納所有字元值 + EOF (-1)

4. 終端機下 Ctrl+D (Linux) / Ctrl+Z (Windows) 行為詳解

終端機驅動程式預設處於標準模式(行緩衝,Canonical Mode),輸入以行為單位送達程式。Ctrl+D 的作用取決於當前行已輸入內容:

當前行狀態按鍵效果
空行(剛提示輸入)Ctrl+D 一次產生 EOF,getchar() 回傳 EOF,程式結束讀取。
已輸入字元,未換行Ctrl+D 一次將當前行內容送達程式(相當於換行),不產生 EOF。
已輸入字元,未換行Ctrl+D 連按兩次第一次送達當前行,第二次產生 EOF。
已輸入字元並按 EnterCtrl+D 一次產生 EOF(因為新行是空的)。

總結: 只有在 getchar() 等待新的一行輸入時,直接按 Ctrl+D 才相當於檔案結束符。

5. 範例驗證

#include <stdio.h>
int main(void) {
    int c;
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}
  • 輸入 abc + Ctrl+D → 螢幕顯示 abcabc(第一次 Ctrl+D 送達 "abc",程式印出 "abc";第二次 Ctrl+D 結束)。
  • 輸入 abc + Enter → 顯示 abc(換行),等待下一行。

6. 非標準模式 (Raw Mode)

若需逐字元即時處理(如遊戲、密碼輸入),可切換終端機至 Raw Mode:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int c;
    system("stty raw");      // 進入 Raw Mode:逐字元傳送,無回顯、無行編輯
    c = getchar();           // 讀取單一字元即返回
    putchar(c);
    system("stty cooked");   // 恢復標準模式
    return 0;
}

此時 getchar() 不需 Enter 或 Ctrl+D 即可返回,Ctrl+D 也不再有特殊含義(會被視為普通字元 0x04)。

結語

  • EOF 是狀態碼,非資料字元。
  • 讀取迴圈務必用 int 變數接收回傳值。
  • 迴圈結束後,必須用 feof()/ferror() 區分正常結束與錯誤。
  • 終端機 Ctrl+D 行為受行緩衝模式影響,理解「送達當前行」與「產生 EOF」的區別至關重要。
Copyright © Windows教程網 All Rights Reserved