首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言星期首字母判斷:scanf 緩衝區殘留導致跳過輸入的經典陷阱

     編輯:程式設計綜合問答

問題現象

輸入 `s` 或 `t` 後提示「輸入下一個字母」,但 `scanf_s("%c", &ch)` 直接讀到換行符,導致程序直接退出,無顯示結果。

根因分析

  • 首次 `getchar()` 讀取字母(如 `s`),**緩衝區殘留 `\n`**。
  • 第二次 `getchar()` **吞掉 `\n`**(代碼中有額外 `getchar()`)。
  • 進入 `switch case 's':`,調用 `scanf_s("%c", &ch)` → **直接讀取緩衝區下一字符**,若無輸入則阻塞,若有殘留 `\n` 則讀到 `\n`,不匹配 `'a'`/`'u'`,無輸出直接 `break` 退出。

修復方案

方案一:統一用 getchar(),手動清理緩衝區(推薦)


#include 

int main(void) {
    puts("請輸入星期首字母 (m/t/w/f/s):");
    int ch = getchar(); // 讀首字母
    while (getchar() != '\n'); // 清空緩衝區剩餘字符(含換行)
    
    switch (ch) {
        case 'm': puts("Monday"); break;
        case 't': 
            puts("請輸入第二字母 (u/h):");
            ch = getchar();
            while (getchar() != '\n'); // 清理
            if (ch == 'u') puts("Tuesday");
            else if (ch == 'h') puts("Thursday");
            break;
        case 'w': puts("Wednesday"); break;
        case 'f': puts("Friday"); break;
        case 's':
            puts("請輸入第二字母 (a/u):");
            ch = getchar();
            while (getchar() != '\n');
            if (ch == 'a') puts("Saturday");
            else if (ch == 'u') puts("Sunday");
            break;
        default: puts("輸入錯誤");
    }
    return 0;
}

方案二:scanf 加空格跳過空白字符


scanf(" %c", &ch); // %c 前加空格:自動跳過 \n, space, \t 等空白字符

方案三:fgets 讀整行再解析(最健壯)


char buf[10];
fgets(buf, sizeof(buf), stdin); // 讀整行含換行
sscanf(buf, " %c", &ch);        // 解析首非空白字符

核心知識點總結

函數行為避坑技巧
`getchar()`讀單字符,含換行後跟 `while(getchar()!='\n');` 清理
`scanf("%c")`讀單字符,**不跳過空白**用 `" %c"` (前加空格) 跳過空白
`scanf("%d/%s")`**自動跳過空白**無需額外處理
`fgets()`讀整行(含換行)最安全,配合 sscanf 解析

完善版代碼(含大小寫兼容、循環輸入)


#include 
#include 

int main() {
    char input[10];
    while (1) {
        printf("輸入星期首字母 (m/t/w/f/s, q退出): ");
        if (!fgets(input, sizeof(input), stdin)) break;
        if (input[0] == 'q' || input[0] == 'Q') break;
        
        char first = tolower(input[0]);
        switch (first) {
            case 'm': puts("Monday"); break;
            case 't':
                printf("輸入第二字母 (u/h): ");
                fgets(input, sizeof(input), stdin);
                if (tolower(input[0]) == 'u') puts("Tuesday");
                else if (tolower(input[0]) == 'h') puts("Thursday");
                else puts("錯誤");
                break;
            case 'w': puts("Wednesday"); break;
            case 'f': puts("Friday"); break;
            case 's':
                printf("輸入第二字母 (a/u): ");
                fgets(input, sizeof(input), stdin);
                if (tolower(input[0]) == 'a') puts("Saturday");
                else if (tolower(input[0]) == 'u') puts("Sunday");
                else puts("錯誤");
                break;
            default: puts("無效輸入");
        }
    }
    return 0;
}

總結

`scanf("%c")` **不跳過換行符** 是 C 輸入經典大坑。統一使用 `fgets` 讀行 + `sscanf` 解析,或 `getchar` 配合清理緩衝區,可徹底避免此類問題。`scanf_s` 為 MSVC 專有,移植性較差,建議項目中統一標準 C 輸入方式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved