現象:輸入 aa bb 回車後才輸出 END1,而非輸入 aa 空格後立即輸出。這揭示了 標準輸入默認行緩衝 以及 scanf 格式化掃描語義 的雙重作用。
用戶鍵盤輸入
↓
內核終端驅動 (行緩衝:收集字符直到 \n)
↓ 回車鍵觸發
標準輸入流 stdin (FILE*)
↓
scanf("%s", a1) 解析流程:
1. 跳過空白字符 (空格、\t、\n)
2. 讀取非空白字符序列 → "aa"
3. 遇到空格 停止,空格留在流中
4. 返回 1,賦值 a1="aa"
↓
printf("END1") 執行輸出
↓
scanf("%s", a2) 繼續:
1. 跳過殘留空格
2. 讀取 "bb"
3. 遇到 \n 停留
↓
...
| 概念 | 說明 |
|---|---|
| 行緩衝 | 終端驅動收集整行(以 \n 結束)後才提交給進程 stdin |
%s 掃描語義 | 「跳過前導空白 → 讀取非空白序列 → 遇到空白停止,空白推回流中」 |
| 空格不觸發 | 空格是 %s 的分隔符,而非終止符;終止符是 EOF 或下一個掃描失敗 |
| 回車觸發 | \n 結束行緩衝收集,使 stdin 獲得完整數據供 scanf 解析 |
#include
int main() {
char a[10], b[10];
printf("Input: ");
scanf("%s", a); // 輸入 "hello world" + 回車
printf("a=[%s]\n", a); // 輸出 a=[hello]
scanf("%s", b); // 直接讀取殘留 "world"
printf("b=[%s]\n", b); // 輸出 b=[world]
return 0;
}
若需「輸入一字符即處理」(如遊戲、實時交互),標準 C 無跨平台方案:
termios 設置原始模式、select 非阻塞檢測_kbhit() / _getch() (conio.h)ncurses、SDL、GLFWscanf 配合 fgets + sscanf 更健壯(避免殘留換行符干擾)fgets(buf, sizeof(buf), stdin) 讀取完整行,再用 strtok/sscanf 分割while (getchar() != '\n');(僅用於簡單場景)理解「終端行緩衝」與「scanf 格式掃描」的分層機制,能精準預測輸入輸出行為,避免調試時的困惑。