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

C 語言 scanf 格式匹配陷阱:為什麼輸入字符會導致死循環?

     編輯:C 語言問答

現場還原:經典死循環代碼

for (; i != 234; ) {
    printf("數字");
    scanf("%d", &a[k]);
    printf("字母");
    scanf("%d", &i);   // 💣 期望輸入字母,卻用 %d
    k++;
}

核心原因:輸入流殘留與格式不匹配

  1. scanf("%d", &i) 期望讀取整數,跳過空白字符 (空格、換行、Tab)。
  2. 用戶輸入字母 a 並按 Enter,緩衝區剩 "a\n"。
  3. %d 發現首字符 'a' 非數字,**匹配失敗**,不消耗任何字符**,i 值不變**,緩衝區仍殘留 "a\n"。
  4. 迴圈條件 i != 234 依然成立,進入下一次迭代。
  5. 再次執行到 scanf("%d", &i),面對同樣的 "a\n",再次匹配失敗……**無限循環**。

修正方案對比

方案代碼片段優點缺點
改用字符讀取scanf(" %c", &ch); (注意前導空格吃掉換行)簡單、直接讀字符需自行驗證是否為數字/字母
讀整行再解析fgets(buf, sizeof(buf), stdin); sscanf(buf, "%d", &i);完全控制輸入、易於錯誤恢復稍顯繁瑣
檢查 scanf 返回值if (scanf("%d", &i) != 1) { /* 清理緩衝區 */ while (getchar() != '\n'); }標準做法、健壯需記住清理緩衝區模式

進階案例:混合讀取數字與字符

int putin(int a[]) {
    int k = 0;
    char ch;
    for (; ch != 'k'; ) {          // ⚠️ ch 未初始化!
        printf("數字\n");
        scanf("%d", &a[k]);
        printf("字母\n");
        scanf(" %c", &ch);         // 前導空格吃掉殘留換行
        k++;
    }
    return k;
}

三個關鍵修正:

  1. char ch = 0; 初始化,避免首次判斷用到垃圾值。
  2. scanf(" %c", &ch) 前導空格自動跳過空白字符 (含上一行殘留的 \n)。
  3. printf("數字\\n") 加換行,提示與輸入分行,體驗更好。

scanf 返回值檢查模板 (必背)

int x;
while (1) {
    printf("請輸入整數: ");
    int ret = scanf("%d", &x);
    if (ret == 1) break;           // 成功讀到 1 個整數
    if (ret == EOF) exit(1);       // Ctrl+D / Ctrl+Z 結束
    // ret == 0:匹配失敗,清理緩衝區
    while (getchar() != '\n');     // 吃掉本行剩餘字符
    printf("輸入無效,請重試。\n");
}

核心心法
1. scanf 返回 成功匹配並賦值的項目數,而非讀取字符數。
2. 匹配失敗不消耗輸入**,必須手動清理緩衝區。
3. 生產級代碼 永不直接信任 scanf,一律用 fgets + sscanf/strtol 組合。
4. %c 不會自動跳過空白,需在格式串加空格 " %c"。

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