執行以下加油計費程式時,第二個 scanf("%c", &s) 被跳過,直接讀到換行符,導致服務類型選擇失效:
printf("請輸入服務類型:\n");
printf("a.自己加\n");
printf("b.自助加\n");
scanf("%c", &s); // 這裡直接讀到上一個 scanf 留下的 '\n'
scanf("%f", &x) 讀取浮點數後,緩衝區殘留換行符 \n。緊接著的 scanf("%c", &s) 讀取單一字元,直接消費這個換行符,而非使用者輸入的 'a' 或 'b'。
fflush(stdin)(不推薦,非標準)scanf("%f", &x);
fflush(stdin); // 僅 Windows/MSVC 支援,C 標準未定義
scanf("%c", &s);
scanf(" %c", &s); // 空白會跳過所有空白字元(含 \n、\t、空格)
getchar() 吞噬換行符scanf("%f", &x);
getchar(); // 讀走殘留的 \n
scanf("%c", &s);
fgets + sscanf(最穩健)char buf[32];
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%f", &x);
fgets(buf, sizeof(buf), stdin);
sscanf(buf, " %c", &s);
#include <stdio.h>
#include <stdlib.h>
int main() {
float x, y, z, k;
char s, q;
printf("請輸入加油量:\n");
scanf("%f", &x);
printf("請輸入服務類型:\n");
printf("a.自己加\n");
printf("b.自助加\n");
scanf(" %c", &s); // 關鍵:前面加空白
switch(s) {
case 'a': z = 0.95; break;
case 'b': z = 0.90; break;
default: printf("error\n"); return 1;
}
printf("請輸入汽油品種:\n");
scanf(" %c", &q); // 同樣加空白
switch(q) {
case 'a': y = 3.25; break;
case 'b': y = 3.00; break;
case 'c': y = 2.75; break;
default: printf("error\n"); return 1;
}
k = x * y * z;
printf("所購汽油價格:%.2f\n", k);
return 0;
}
| 場景 | 建議寫法 | 說明 |
|---|---|---|
| 讀取單一字元 | scanf(" %c", &ch) | 前置空白跳過空白字元 |
| 讀取字串 | scanf("%s", str) | 自動跳過前導空白 |
| 混合輸入 | fgets + sscanf | 逐行讀取,避免緩衝區殘留 |
核心原則:%c 是唯一不自動跳過空白字元的格式指示符,使用時務必在前面加空白或預先清理緩衝區。