語法書 / AA 競程語法書 上冊 / 第四單元 / EOF 與常見輸入模式

4.8 EOF 與常見輸入模式

不同題目的輸入方式不一樣。有的會告訴你「輸入共 N 組」,有的說「讀到檔案結尾」,有的說「讀到 0 就停止」。你得能應付各種模式。

EOF(End of File): 表示沒有更多輸入資料了。

檢查 EOF 的方法:

if (cin.eof()) {
    // 已經沒有輸入了
}

但更常用的是利用 cin >> var 的返回值:

while (cin >> n) {
    // 成功讀入 n,繼續處理
}
// 讀入失敗時迴圈停止(包括 EOF 和格式錯誤)

範例程式碼

範例 1:讀到檔案結尾

#include<iostream>
using namespace std;
int main() {
    int n;
    // 只要能成功讀入一個整數,就繼續迴圈
    while (cin >> n) {
        cout << "You entered: " << n << "\n";
    }
    cout << "Done reading.\n";

    return 0;
}

執行範例:(手動輸入 3 5 7,然後按 Ctrl+D 表示 EOF)

You entered: 3
You entered: 5
You entered: 7
Done reading.

範例 2:讀到 0 就停止

#include<iostream>
using namespace std;
int main() {
    int n;
    while (cin >> n && n != 0) {
        cout << "Number: " << n << "\n";
    }
    cout << "Got 0, stop reading.\n";

    return 0;
}

執行範例:(手動輸入 10 20 30 0)

Number: 10
Number: 20
Number: 30
Got 0, stop reading.

為什麼 while (T--) 能跑 T 次?

第一種模式的 while (T--) 用到了 4.7 的後置遞減:每一圈先拿 T 現在的值當條件(非 0 就繼續),再把 T 減 1。所以 T = 3 時會做 3 圈(條件依序用到 3、2、1),等 T 變成 0 時條件不成立、正好停下。它等價於 for (int k = 0; k < T; k++),只是更短。逐圈推導、以及 while (--T) 為什麼少一圈還會在 T = 0 時暴走,見 4.7 的「應用」段。

注意T 在迴圈過程中被改掉了(跑完會停在 -1),所以迴圈結束後別再拿原本的 T 當次數用。不放心的話,初學就用 for (int k = 0; k < T; k++)T 完全不會被動到。

動手試試看

  1. (EOF) 讀入一堆整數直到檔案結尾,輸出它們的平均值(同時累加總和與個數,最後相除)。
  2. (讀到 0 停) 讀入整數直到遇到 0,輸出其中的最大值(0 不算)。
  3. (先給組數) 第一行是組數 T,接下來 T 行各一個整數,把每個整數乘以 2 後印出。用 while (T--)for 都可以。