根据 sscanf() 的手册页,* 字符
An optional '*' assignment-suppression character: scanf() reads input as directed by the conversion specification, but discards the input.
由此,我(对吗?)假设类似
sscanf(string,"%*[^|]%*c%[^|]%*c", vars)
将接受输入“text|neededtext|”,忽略第一个“|”之前的所有文本(即从标准输入中删除它?),忽略(并从标准输入中删除)下一个字符,即“|”存储“neededtext”,然后删除最后的“|”字符,将 stdin 留空? 如果是,那么在 sscanf() 调用之后是否需要运行清理函数,以捕获一些奇怪的异常,以防万一出现问题,或者上面的代码总是保证工作?
我已经运行了一些测试,看来 sscanf() 确实消耗了标准输入中的所有字符,但我只是想确定一下。
最佳答案
并非总是如此。请参阅#2
一个@Jonathan Leffler评论说,sscanf()
适用于字符串,并且不影响 stdin
。让我们假设问题是关于 *scanf()
系列的。
*scanf(string,"%*[^|]%*c%[^|]%*c", vars) 的问题
代码不检查
*scanf()
的结果。这导致难以察觉的问题。最好编写一个检查代码。char vars[100]; if (sscanf(string,"%*[^|]%*c%99[^|]%*c", vars) != 1) Handle_Error();
"%*[^|]"
不扫描任何内容,如果前导字符是'|'
,则停止整个扫描功能。"%*[^|]"
扫描 1 个或多个非'|'
,而不是 0 个或多个。因此,上面的“并不总是”。使用scanf()
时,不会消耗任何字符 - 它们保留在stdin
中。"%*[^|]"
后唯一可能继续扫描的字符是'|'
。不妨编码"%*[^|]%|"
而不是"%*[^|]%*c"
sscanf()
与scanf()
和fscanf()
的不同之处在于,后两者可以扫描并保存 null字符'\0'
。sscanf()
在到达空字符时停止扫描。 IMO:应避免将"%s"
和"%[^...]
与fscanf() scanf()
一起使用,以防止黑客利用。OP 的fgets()+sscanf()
是更好的方法。%[^|]
缺少宽度。如果没有此限制,就无法防止缓冲区溢出。请参阅#1。
末尾的 "%*c"
可能会也可能不会扫描字符。结果值并不反射(reflect)其成功或失败,因为带有'*'
的扫描指令不会直接影响返回值。如果需要成功尾随扫描"%*c"
(可能是每个点 #3 的"|"
),建议使用"%n"
检测扫描是否继续进行到此为止。char vars[100]; int n = 0; sscanf(string,"%*[^|]|%99[^|]| %n", vars); if (n > 0) Success(); // May also want to use if (string[n]) Fail_ExtraTextOnLine();
在 C 语言中,
<%*[^|]
是scanf
说明符,而不是分隔符。
关于c - 使用 %*[^|] 分隔符时 sscanf() 是否从标准输入中删除字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32533814/