我有以下c代码
if (sscanf(input, "s %d\n", &value) == 1){}
假设解析以下内容
s -inf
....
s 0
s 1
s 2
....
s inf
但不是
之类的东西s 5junkjunkjunk
因为它不匹配,因为%d
和\n
之间存在某些内容。但它确实有效,即使它不符合格式字符串。
答案 0 :(得分:1)
如果您阅读docs for scanf()
,您会发现格式字符串中每个空白字符的外观都与输入中的任意数量的空白字符(包括零)相匹配。 sscanf()
不能强制匹配整个字符串 - 如果它匹配格式字符串中的所有内容,它将“成功”,即使这会使其他字符(junkjunkjunk
)未使用。
答案 1 :(得分:1)
这是(一个)为什么永远不应该使用*scanf
的原因之一:强大地处理格式错误的输入是非常困难的。
解析这类内容的正确方法是:使用fgets
(如果有的话,使用getline
)来读取整行,手动检查并跳过前导"s "
,然后使用strtod
解析数字,然后检查strtod
是否设置*endp
以指向换行符。
如果语法甚至比您的语法更复杂,那么可能需要时间到达lex
和yacc
。
答案 2 :(得分:1)
接受回答后
inf
很好地被视为一个浮点。
同意scanf()
很麻烦,但sscanf()
是多才多艺的。
注意:"%n"
报告char
扫描的数量,但不会导致sscanf()
结果。
char buf[100];
if (fgets(buf, sizeof buf, input) == NULL) EOForIOerror();
int n;
double x;
if (sscanf("s %lf %n", &x, &n) != 1 || buf[n]) ScanFailure();
// if needed
if (!isinf(x) && round(x) != x) NumberIsNotInfinityNorWholeNumber();
// x is good to go
详细说明:
如果未找到合法号码,则sscanf()
不会返回1并且会调用ScanFailure()
。
Else是一个合法的号码," %n"
会扫描任意数字0或更多的尾随空格,例如'\n'
。然后它在n
中设置扫描的偏移量。这个位置将是数字后的第一个非白色空间。如果不是'\0'
,则会调用ScanFailure()
。