int sscanf(const char *str, const char *format, ...);
sscanf 從固定字串讀取格式化資料,類似 scanf 但輸入源為記憶體緩衝區而非標準輸入。回傳成功轉換的參數個數,失敗回傳 EOF(通常為 -1)。
format 可包含一個或多個轉換規格:
%[*][width][{h|l|ll|L}]type
*:抑制賦值,跳過該欄位不存入引數(如 %*d、%*s)。width:最大讀取寬度(字元數)。h/l/ll/L:引數大小修飾(h=short, l=long/double, ll=long long, L=long double)。type:轉換類型(d、i、u、x、o、f、e、g、s、c、[...]、p、n 等)。%[...] 可定義接受字元集合,支援範圍與排除:
| 格式 | 含義 | 貪婪性 |
|---|---|---|
%[a-z] | 匹配 a-z 任意字元 | 是(盡可能多) |
%[aB'] | 匹配 a、B、' 中任一 | 是 |
%[^a] | 匹配非 a 的任意字元 | 是 |
%[^A-Z] | 匹配非大寫字母 | 是 |
注意:%[] 與 %[^] 為非法格式;^ 僅在開頭表示排除。
char buf[512] = {0};
sscanf("123456", "%s", buf); // buf = "123456"
sscanf("123456", "%4s", buf); // 寬度限制:buf = "1234"
sscanf("123456 abcdedf", "%[^ ]", buf); // 遇到空格停止:buf = "123456"
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); // buf = "123456abcdedf"
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf); // 遇到大寫停止:buf = "123456abcdedf"
// 取 / 和 @ 之間:先略過 "iios/",再讀非 @ 字元
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); // buf = "12DDWDFF"
int a, b, c;
sscanf("2006:03:18", "%d:%d:%d", &a, &b, &c); // a=2006, b=3, c=18
char t1[16], t2[16];
sscanf("2006:03:18 - 2006:04:18", "%s - %s", t1, t2); // t1="2006:03:18", t2="2006:04:18"
// 或更精確:
sscanf("2006:03:18 - 2006:04:18", "%[0-9:] - %[0-9:]", t1, t2);
float price; int qty;
char cat[21], name[21], vendor[21], sku[21];
char buf[201];
fgets(buf, 200, fp);
sscanf(buf, "%20[^#]#%20[^#]#%f#%i#%20[^#]#%20[^\n]",
name, sku, &price, &qty, cat, vendor);
%20[^#]#:最多讀 20 字元,遇 # 停止(不含 #)。%f#、%i#:讀數值後遇 # 停止。%20[^\n]:最多 20 字元,忽略行尾換行。char s[] = "notepad=1.0.0.1001";
char filename[32];
sscanf(s, "%*[^=]=%s", filename); // filename = "1.0.0.1001"
%20s、%20[^#])防止緩衝區溢位。%n 不消耗輸入:記錄截至目前已讀取的字元數,用於後續處理。%ms(自動分配記憶體),屬 GNU 擴展,非標準 C。sscanf 的強大在於格式字串的表達力,特別是掃描集 %[...] 與抑制賦值 * 的組合,能以極簡潔程式碼完成複雜字串剖析。熟練掌握這些模式,能大幅減少手動字串處理的錯誤與代碼量。