%[chars]:匹配 chars 中任意字符,貪婪讀取直到遇到非集合字符。
%[^chars]:匹配 非 chars 中字符,遇到集合字符停止。
| 格式串 | 匹配內容 | 典型用途 |
|---|---|---|
| %[a-z] | 小寫字母 | 讀取單詞 |
| %[a-zA-Z0-9] | 字母數字 | 讀取標識符 |
| %[^ \n\t] | 非空白字符 | 讀取一個 token |
| %[^=] | 非 '=' 字符 | 解析 key=value |
| %[^\n] | 整行 (含空格) | 讀取一行文本 |
| %*[^=]=%s | 跳過 key,讀 value | 提取值部分 |
char line[100];
scanf("%[^\n]", line); // 讀到換行符停止,不包含 \n
getchar(); // 吸收殘留的 \n
char key[32], val[64];
char *s = "username=admin";
sscanf(s, "%[^=]=%s", key, val);
// key="username", val="admin"
char version[32];
char *s = "app=v1.2.3";
sscanf(s, "%*[^=]=%s", version);
// version="v1.2.3", key 被丟棄
char buf[41];
scanf("%40c", buf); // 精確讀 40 字符,不加 \0
buf[40] = '\0'; // 手動添加結束符
| 函數 | 輸入源 | 適用場景 |
|---|---|---|
| scanf | stdin | 交互式輸入 |
| fscanf | FILE* | 文件解析 |
| sscanf | char* | 字符串解析、协议解包 |
陷阱:用 fscanf 判斷文件結束不可靠,匹配失敗返回 0 而非 EOF。應配合 feof() 或檢查實際讀取字節數。
%[*][width][{h|l|ll|L|j|z|t}]type
* : 抑制賦值 (不存儲)
width : 最大讀取字符數
h : short / unsigned short
l : long / double / wchar_t*
ll : long long
L : long double
j : intmax_t
z : size_t
t : ptrdiff_t
type : d i u o x X f e g a c s p n [...]
char s[10]; scanf("%s", s); 輸入超過 9 字符會溢出。scanf("%9s", s); 或用 fgets。
scanf("%d", &n); scanf("%[^\n]", s); 第二次讀到空行。getchar() 或 scanf(" %[^\n]", s) (前導空格吃掉空白)。
scanf("%c", &c); 會讀取空格/換行。scanf(" %c", &c); 前導空格跳過空白。
scanf("%[0-9]", s); 輸入 "abc" → 返回 0,'a' 留在緩衝區,下次 scanf 仍讀 'a'。scanf 掃描集功能強大但易誤用。掌握 %[^chars] 反向匹配、* 抑制賦值、width 防溢出三大技巧,配合 fgets 讀行、sscanf 解析的組合拳,可處理 90% 的文本輸入場景。複雜協議解析建議使用專用解析器生成器 (lex/yacc) 或現代 C++ 庫。