初學C語言時,常遇到getchar()讀取字符與EOF判斷不符合預期的問題。本文深入解析輸入緩沖區機制,解釋為什麼只有單獨輸入EOF才能正常退出循環,以及混合輸入時出現異常輸出的原因。
char ch = NULL;
while ((ch = getchar()) != EOF) {
if (!isalpha(ch))
printf("%c isn't a letter. -1\n");
else {
if (isupper(ch))
printf("%c is the %d in the alphabet\n", ch, ch - 'A' + 1);
else
printf("%c is the %d in the alphabet\n", ch, ch - 'a' + 1);
}
}
輸入字符後按回車,再輸入EOF(Ctrl+Z),程序輸出奇怪內容如 c isn't a letter. -1。
getchar() 從標準輸入緩沖區讀取字符\n)才進入緩沖區getchar() 每次調用只讀取緩沖區的一個字符Ctrl+Z(ASCII 0x1A)Ctrl+Z 必須位於行首(即緩沖區第一個字符),getchar() 才會返回 EOF(-1)Ctrl+Z 只是緩沖區中的普通字符 0x1A,不會觸發 EOF輸入:abc + Enter + Ctrl+Z + Enter
'a','b','c','\n',0x1A,'\n'getchar() 讀取 'a',非 EOF,進入循環'b'、'c'、'\n'0x1A 時,不視為 EOF,作為普通字符處理'\n'getchar() 等待新輸入在新行開頭直接按 Ctrl+Z + Enter,緩沖區首字符為 0x1A,getchar() 返回 -1,循環結束。
int ch; // 用 int 接收,可容納 EOF(-1)
while ((ch = getchar()) != EOF) {
if (ch == '\n') continue; // 跳過換行符
if (!isalpha(ch))
printf("%c isn't a letter. -1\n", ch);
else {
if (isupper(ch))
printf("%c is the %d in the alphabet\n", ch, ch - 'A' + 1);
else
printf("%c is the %d in the alphabet\n", ch, ch - 'a' + 1);
}
}
int 而非 char,因為 EOF 通常為 -1,超出 char 範圍ch == '\n' 判斷跳過換行符printf 格式串補全參數理解行緩沖、EOF 在行首才生效、int 接收返回值這三點,即可避開 C 語言控制台輸入的常見坑。