OJ 題目常見讀入迴圈寫法:
while (scanf("%d", &a) != EOF) { ... } // 正確
while (1 == scanf("%d", &a) != EOF) { ... } // 錯誤:導致超時
== 與 != 優先級相同,左結合。1 == scanf(...) != EOF 等價於 (1 == scanf(...)) != EOF。scanf 成功讀入 1 個整數 → 回傳 1。1 == 1 → 真 (1)。1 != EOF (EOF 通常為 -1) → 真 (1)。scanf 讀取失敗 (輸入非數字) → 回傳 0。1 == 0 → 假 (0)。0 != EOF → 真 (1)。scanf 反覆失敗回傳 0,迴圈無限空轉 → OJ 判定超時 (TLE)。// 1. 最標準:直接判斷回傳值與 EOF
while (scanf("%d", &a) != EOF) { ... }
// 2. 明確判斷成功讀入個數 (推薦,語意清楚)
while (scanf("%d", &a) == 1) { ... }
// 3. C++ 風格:配合 iostream
while (cin >> a) { ... }
若必須用 scanf 且輸入可能含非數字,讀失敗後需手動清緩衝區:
while (true) {
int ret = scanf("%d", &a);
if (ret == EOF) break; // 檔案結束
if (ret == 1) { /* 處理 a */ continue; }
// ret == 0:讀失敗,吃掉一個非空白字元
scanf("%*c"); // 或 getchar()
}
「不要在條件判斷裡玩花樣,
scanf回傳值直接比EOF或預期個數,失敗時記得清緩衝區。」
記住這原理,OJ 讀入迴圈再也不會莫名超時。