初學 C 語言時,getchar()、scanf()、gets() 混用常導致「輸入被跳過」的現象。本質上是**標準輸入流(stdin)的行緩衝機制**與**換行符殘留**共同作用的結果。本文深入剖析原理並給出解決方案。
getchar() 每次只從緩衝區取**一個字符**。w\n,緩衝區實際包含 'w' 和 '\n' 兩個字符。char a;
char b[100], c[100];
scanf("%c", &a); // 用戶輸入:x + Enter
gets(b); // 本想讀一行,實際讀到殘留的 '\n' → 空串
gets(c); // 這才真正等待用戶輸入
原因:scanf("%c") 只消費 'x','\n' 留在緩衝區。gets() 遇到 '\n' 即以為讀完一行,返回空字符串。
char ch1 = getchar(); // 讀 'x'
char ch2 = getchar(); // 直接讀到殘留的 '\n',不會等待
scanf("%c", &a);
getchar(); // 吸收殘留的 '\n'
gets(b); // 正常工作
scanf("%c ", &a); // %c 後加空格:跳過任意數量空白(含 \n)
gets(b);
%c 中的空格會指示 scanf **讀取並丟棄** 後續所有空白字符,直到遇到非空白字符或 EOF。這比額外 getchar() 更健壯(能處理多個空格/換行)。
char line[100];
fgets(line, sizeof(line), stdin); // 讀整行(含 \n)
sscanf(line, "%c", &a); // 從行中解析
fgets(b, sizeof(b), stdin); // 直接讀下一行
fgets 會把 \n 一併讀入,後續解析不受殘留影響。gets(已移除 C11,極不安全)。| 場景 | 問題 | 推薦做法 |
|---|---|---|
| scanf("%c") 後接 gets/fgets | 殘留 \n 導致跳過 | scanf("%c ") 或 fgets+sscanf |
| 連續 getchar() | 第二次讀到 \n | 預期行為;若需跳過,手動 getchar() |
| 混合輸入 | 緩衝區狀態難控制 | 全程用 fgets 讀行,再用 sscanf/strtok 解析 |
gets/scanf 做行讀取,改用 fgets。sscanf、strtok、手寫解析器。scanf,格式串中善用空白字符跳過殘留(如 "%d %c %s")。getchar() 並自行處理緩衝區。理解「緩衝區 + 行提交」模型,輸入問題將不再是難題。