c - 使用 %*[^|] 分隔符时 sscanf() 是否从标准输入中删除字符?

标签 c stdin delimiter scanf

根据 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) 的问题

  1. 代码不检查*scanf()的结果。这导致难以察觉的问题。最好编写一个检查代码。

    char vars[100];
    if (sscanf(string,"%*[^|]%*c%99[^|]%*c", vars) != 1) Handle_Error();
    
  2. "%*[^|]" 不扫描任何内容,如果前导字符是 '|',则停止整个扫描功能。 "%*[^|]" 扫描 1 个或多个非 '|',而不是 0 个或多个。因此,上面的“并不总是”。使用 scanf() 时,不会消耗任何字符 - 它们保留在 stdin 中。

  3. "%*[^|]" 后唯一可能继续扫描的字符是 '|'。不妨编码 "%*[^|]%|" 而不是 "%*[^|]%*c"

  4. sscanf()scanf()fscanf() 的不同之处在于,后两者可以扫描并保存 null字符'\0'sscanf() 在到达空字符时停止扫描。 IMO:应避免将 "%s""%[^...]fscanf() scanf() 一起使用,以防止黑客利用。OP 的 fgets()+sscanf() 是更好的方法。

  5. %[^|] 缺少宽度。如果没有此限制,就无法防止缓冲区溢出。请参阅#1。

  6. 末尾的
  7. "%*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();
    
  8. 在 C 语言中,%*[^|]scanf 说明符,而不是分隔符。

    <

关于c - 使用 %*[^|] 分隔符时 sscanf() 是否从标准输入中删除字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32533814/

相关文章:

c - strncpy 并使用 sizeof 复制最大字符数

有人可以和我一起浏览这个 MIPS 代码吗?

io - 在 Rust 中是否有丢弃输入的标准方法?

c - 如何检索字符串的一部分?

c - fscanf 读取空格分隔的数据直到返回

javascript - 如何更改 mustache.js 的默认分隔符?

c - 使用 SSE 内在函数的矩阵乘法

c - scanf GCC for long double

c - 如何在 C 中使用 EOF 标准输入

c - 逗号分隔字符串的解析函数