sscanf()在使用%* [^ |]分隔符时从stdin删除字符?

时间:2015-09-12 00:10:01

标签: c stdin delimiter scanf

根据sscanf()的手册页,*字符

  

可选的'*'赋值抑制字符:scanf()读取输入   按照转换规范的指示,但丢弃输入。

由此,我(正确地?)假设像

这样的东西
[eggs, lasers, hats, pie]
eggs
lasers
hats
pie

eggs
pie

将输入“text | neededtext |”,忽略第一个“|”之前的所有文本(即从stdin中删除它?),忽略(并从stdin中删除)下一个字符,即“|”存储“requiredtext”然后删除最后的“|”性格,让stdin空着? 如果是,那么在sscanf()调用之后是否需要运行清理函数,以便在出现问题时捕获一些奇怪的异常,或者上面的代码是否始终保证有效?

我已经运行了一些测试,似乎sscanf()确实吃掉了stdin中的所有字符,但我只想确定。

1 个答案:

答案 0 :(得分:0)

并非总是如此。见#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. 如果前导字符为"%*[^|]",则
  3. '|'不扫描任何内容并停止整个扫描功能。 "%*[^|]"扫描1个或多个非'|',而不是0或更多。因此,"并非总是"以上。使用scanf()时,不会消耗任何字符 - 它们会保留在stdin

  4. "%*[^|]"继续扫描后唯一可能的字符为'|'。代码"%*[^|]%|"可能比"%*[^|]%*c"

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

  7. %[^|]缺少宽度。如果没有此限制,则不会阻止缓冲区溢出。见#1。

  8. 最后
  9. "%*c"可能会扫描或不扫描角色。结果值不反映其成功或失败,因为'*'的扫描指令不直接对返回值有贡献。如果需要"%*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();
    
  10. 在C中,%*[^|]scanf 说明符,而不是分隔符。