scanf_s 緩衝區殘留換行符問題分析Visual Studio 專用的安全函式 scanf_s 在讀取字符時,常因上一個 scanf_s 遺留的換行符 \n 被直接讀取,導致程式「跳過」使用者輸入。本文深度剖析原因並提供三種標準解決方案。
printf("是否繼續 (y/n): ");
scanf_s("%c", &d, 1); // 只讀取 1 個字符
// 若前一次 scanf_s("%d", &k) 後用戶按了 Enter
// 緩衝區殘留 '\n',此處直接讀到 '\n',d = '\n'
scanf_s("%d", &k) 讀取整數後,停留在換行符前,換行符留在 stdin 緩衝區。scanf_s("%c", &d, 1) 不跳過空白字符(含 \n、 、\t),直接讀取下一個字符——即殘留的 \n。y 或 n。
scanf_s(" %c", &d, 1); // %c 前加一個空格
// 空格指示 scanf_s「跳過任意數量空白字符(含 \n)」
getchar() 清理
printf("是否繼續 (y/n): ");
getchar(); // 吞掉殘留的 \n
scanf_s("%c", &d, 1);
缺點:若緩衝區有多餘字符(如使用者輸入 yes\n),單一 getchar() 不夠。
int ch;
while ((ch = getchar()) != '\n' && ch != EOF); // 清空整行
scanf_s("%c", &d, 1);
scanf` vs `scanf_s 關鍵差異| 特性 | scanf (C 標準) | scanf_s (MSVC 延伸) |
|---|---|---|
| 字符陣列參數 | scanf("%s", buf) | scanf_s("%s", buf, sizeof(buf)) 需傳緩衝區大小 |
字符讀取 %c | scanf("%c", &c) | scanf_s("%c", &c, 1) 需傳 1 |
| 跨平台可攜性 | 全平台 | 僅 MSVC / Windows |
| 緩衝區溢位保護 | 無 | 有(需正確傳大小) |
char line[100];
printf("是否繼續 (y/n): ");
if (fgets(line, sizeof(line), stdin)) {
if (sscanf(line, " %c", &d) == 1) {
// 成功讀取第一個非空白字符
}
}
// 優勢:逐行讀取、自動處理換行、緩衝區安全、跨平台
scanf_s 的換行符陷阱是 C 語言初學者在 Windows 平台的必經之痛。掌握「%c 前加空格」或「fgets + sscanf」兩大模式,徹底告別緩衝區殘留問題。長遠來說,建立「輸入即驗證、逐行處理、避免 scanf 族」的編碼習慣,才是寫出健壯互動程式的正道。