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

C Primer Plus 菜單程序中 scanf 留下換行符導致的隱患分析

     編輯:程式設計疑難解答

問題現象

書籍《C Primer Plus》第 8 章菜單瀏覽示例中提到:若在 count() 函數裡用 scanf("%d", &n) 讀取整數,緩衝區會殘留換行符。隨後調用 get_choice() → get_first() 時,getchar() 會直接讀到這個殘留的換行符,導致菜單邏輯異常。

為什麼測試時「沒問題」?

  • 書中 get_first() 實現為:
    ch = getchar(); while (getchar() != '\n') continue;
    這行代碼會循環吞掉緩衝區剩餘所有字符直到換行符。因此即使上一輪殘留換行符,也會被這裡「吃掉」,不影響下一次菜單選擇。
  • 若你自行修改 get_first() 為單純 return getchar();,則會立即複現「跳過菜單選項」的 Bug。

真正的「不希望的動作」

若 get_first() 不清理緩衝區,用戶輸入 3\n 後:

  1. scanf 讀走 3,留下 \n。
  2. 下一次 get_first() 讀到 \n 返回。
  3. 菜單判斷 ch < 'a' || ch > 'c' 成立,提示「請輸入 a,b,c,q」。
  4. 用戶未輸入任何可見字符,程序卻已進入錯誤提示流程——這就是書中所說的「不希望的動作」。

最佳實踐:統一輸入處理

// 讀取整行並解析,避免殘留字符
char *get_line(char *buf, int size) {
    return fgets(buf, size, stdin);
}

int get_int() {
    char buf[64];
    int val;
    while (1) {
        if (get_line(buf, sizeof(buf)) && sscanf(buf, "%d", &val) == 1)
            return val;
        printf("輸入無效,請重新輸入整數:");
    }
}

理解緩衝區機制,養成「讀整行、再解析」的習慣,徹底避開 scanf 殘留換行符的坑。

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