scanf 是 C 標準庫的格式化輸入函式,從 stdin 讀取並解析資料。雖然常用,但其微妙行為 (如緩衝區殘留、格式匹配失敗) 是新手主要bug來源。本文系統整理用法與避坑指南。
int scanf(const char *format, ...);
| 類別 | 說明 | 範例 |
|---|---|---|
| 格式指定符 | 以 % 開頭,指定讀取型別 | %d, %f, %s, %c, %lf, %p |
| 空白字元 | 空格、換行、Tab:跳過任意多個空白 | "%d %d" 可讀 "1 2" 或 "1\n2" |
| 非空白字元 | 需精確匹配輸入中對應字元 | "%d,%d" 需輸入 "1,2" |
%d 有號十進位整數 %i 自動識別進位 (0x/0 開頭)
%u 無號十進位整數 %o 八進位
%x 十六進位 %f float (單精度)
%lf double (雙精度) %Lf long double
%c 單一字元 (不跳過空白) %s 字串 (遇空白停止)
%p 指標位址 %n 已讀取字元數 (寫入指向的 int)
%[] 掃描集合 (如 %[^\n] 讀整行)
%10s 最多讀 10 字元 (防緩衝區溢位)%*d 讀取但不存儲int a; scanf("%d", a); // 錯誤:傳值,導致未定義行為
scanf("%d", &a); // 正確
char str[100];
scanf("%s", str); // 輸入 "hello world" 僅讀 "hello"
// 解法:用 fgets 或掃描集合
fgets(str, sizeof(str), stdin); // 含換行
scanf("%99[^\n]", str); getchar(); // 讀至換行,清除殘留 \n
int a; char c;
scanf("%d", &a);
scanf("%c", &c); // 直接讀到上一行的 \n
// 解法:在 %c 前加空白跳過空白
scanf(" %c", &c);
while (scanf("%d", &x) != 1) {
// 輸入非數字時,scanf 失敗且不消耗輸入,陷入死循環
// 必須清除緩衝區
int c; while ((c = getchar()) != '\n' && c != EOF);
}
scanf("%d", &x);
getchar(); // 吞掉殘留 \n
fgets(buf, sizeof(buf), stdin);
strtol, strtod 提供完整錯誤檢測、支援進位制、無緩衝區問題。scanf_s 等邊界檢查函式 (MSVC 主導支援)。%99s。" %c" 跳過空白;讀整行用 fgets。-Wall -Wextra,編譯器會捕捉格式字串與參數不匹配。