在 C 語言中,處理標準輸入(stdin)的緩衝區殘留字元是初學者常遇到的棘手問題。當使用 scanf 讀取數值後,緩衝區往往會留下換行符(\n),導致後續的 scanf("%c", &ch) 直接讀取到這個換行符,而非使用者預期的字元輸入。本文將分析幾種常見的清空緩衝區方法,並推薦最具可移植性的最佳實踐。
以下程式碼意圖先讀取一個整數,再讀取一個字元:
#include <stdio.h>
#include <stdlib.h>
int main() {
int num = 0;
char ch = ' ';
scanf("%d", &num);
scanf("%c", &ch); // 預期讀取字元,實際讀到殘留的 '\n'
printf("hello bit\n");
system("pause");
return 0;
}
輸入 7 並按 Enter 後,程式直接輸出 "hello bit",並未等待字元輸入。原因在於 scanf("%d") 讀取整數後,緩衝區仍保留換行符,隨後的 %c 直接讀取了它。
fflush(stdin) —— 不推薦C 標準規定 fflush 僅適用於輸出流(stdout)。雖然 MSVC 等編譯器擴展支援 fflush(stdin),但在 GCC/Clang 上屬於未定義行為,不可移植。
setbuf(stdin, NULL) —— 效果有限將 stdin 設為無緩衝模式。但在某些系統上對交互式輸入無效,且無法清除已存在於緩衝區的字元。
getchar() 清理 —— 推薦做法利用巨集或函式,持續讀取字元直到遇到 \n 或 EOF:
#define CLEAR_BUF() \
do { \
int c = 0; \
while ((c = getchar()) != EOF && c != '\n') \
; \
} while(0)
int main() {
int num = 0;
char ch = ' ';
scanf("%d", &num);
CLEAR_BUF(); // 清空殘留換行符
scanf("%c", &ch);
printf("hello bit\n");
return 0;
}
此法符合 C 標準、跨平台可用、邏輯清晰,是教學與工程實踐的首選。
fflush(stdin)。while ((c = getchar()) != '\n' && c != EOF) 循環清理緩衝區。