从man页面scanf:
\n\n\n指令是以下之一:
\n\n\n
\n- \n
一系列空白字符(空格、制表符、换行符等;请参阅 isspace(3))。该指令匹配输入中任意数量的空格,包括无空格。
- \n
普通字符(即除空格或\'%\'之外的字符)。该字符必须与输入的下一个字符完全匹配。(强调我的)
- \n
转换规范,以“%”(百分比)字符开头。输入的字符序列将根据此规范进行转换,并将结果放置在相应的指针参数中。如果下一项输入与转换规范不匹配,则转换失败\xe2\x80\x94这是匹配失败。
现在,考虑以下代码:
\n\n#include <stdio.h>\n\nint main(void)\n{\n const char* fmt = "A %49s B";\n char buf[50];\n\n printf("%d\\n", sscanf("A foo B", fmt, buf)); // 1\n printf("%d\\n", sscanf("blah blaaah blah", fmt, buf)); // 0\n printf("%d\\n", sscanf("A blah blah", fmt, buf)); // 1\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n第 1 行和第 3 行会打印出来1,因为“A”与“A”的匹配成功,“foo”/“blah”与 的匹配也成功%s。第 2 行打印,0因为“A”无法与“blah”匹配,因此解析在那里停止。
这一切都很好,也很符合逻辑,但是我有什么办法可以检测到在所有转换规范都成功匹配和分配之后发生了匹配失败吗?在这种情况下,返回的值scanf将是我的格式字符串中的转换说明符的数量,因此直到最后我都无法使用它来判断匹配是否成功。
换句话说:sscanf第 3 行中输入的字符串不是“有效”的,因为它不符合 格式A [something] B。我可以用来scanf检测这一点,还是strtok我唯一的选择?
" %n"在格式末尾使用 a 。
指令:
" "扫描 0 个或多个空白。它不会失败。
"%n"保存到目前为止解析的字符数(作为int)。它不会失败。
设置n为 0 并测试以查看它是否发生变化。仅当前面的整个格式成功时才会发生更改。还测试扫描是否以空字符结束 - 从而检测跟踪不需要的文本。
添加的" ",虽然是可选的,但如果非常有用,因为通常是尾随空格(通常是 )'\n',则不会令人反感。它不需要对扫描的文本行进行预处理以删除其行尾。
#include <stdio.h>
void test(const char *s) {
const char* fmt = "A %49s B %n";
char buf[50];
int n = 0;
int cnt = sscanf(s, fmt, buf, &n);
int success = n > 0 && s[n] == '\0';
printf("sscanf():%2d n:%2d success:%d '%s'\n", cnt, n, success, s);
}
int main(void) {
test("A foo B");
test("blah blaaah blah");
test("A blah blah");
test("A foo B ");
test("A foo B x");
test("");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出
sscanf(): 1 n: 7 success:1 'A foo B'
sscanf(): 0 n: 0 success:0 'blah blaaah blah'
sscanf(): 1 n: 0 success:0 'A blah blah'
sscanf(): 1 n: 8 success:1 'A foo B '
sscanf(): 1 n: 8 success:0 'A foo B x'
sscanf():-1 n: 0 success:0 ''
Run Code Online (Sandbox Code Playgroud)
请注意,成功是由n一个人决定的。如果不成功,则buf不应使用目标扫描变量。如果需要部分结果,则使用 的返回值sscanf()。
| 归档时间: |
|
| 查看次数: |
2550 次 |
| 最近记录: |