【问题标题】:sscanf() double showing zerossscanf() 双显示零
【发布时间】:2013-07-31 12:12:16
【问题描述】:

我在使用 sscanf() 函数读取双打时遇到问题。我有一个逗号分隔的文本文件,如下所示:

ABC,DEF,0.465798,0.754314
GHI,JKL,0.784613,0.135264
MNO,OPQ,0.489614,0.745812
etc.

所以我首先使用 fgets() 获取行,然后使用 sscanf() 获取两个字符串和两个双变量。

fgets(buffer, 28, file);
sscanf(buffer, "%4[^,],%4[^,],%lf[^,],%lf[^\n]", string1, string2, &double1, &double2);

printf("%s %s %f %f\n", string1, string2, double1, double2);

但是输出是:

ABC DEF 0.465798 0.000000
GHI JKL 0.784613 0.000000
MNO OPQ 0.489614 0.000000

所以不知何故它不会扫描最后一个浮点数。我试过%lf[^ \t\n\r\v\f,]%lf,但还是不行。

【问题讨论】:

  • 为什么不使用简单得多的格式字符串"%3s,%3s,%lf,%lf"
  • "%4[^,],%4[^,],%lf[^,],%lf[^\n]"更改为"%4[^,],%4[^,],%lf,%lf"
  • 您没有显示您的真实代码(您需要将 &double1 和 &double2 传递给 sscanf)。剪切并粘贴您的实际代码,然后我们可能会提供帮助。
  • 感谢 chux,它成功了,我认为我应该使用 [^,] 双打,因为我没有空格。当我问这个问题时,我有“&”符号(现在编辑了代码),这是一个错字,很抱歉。
  • 由于[^,] 不是以% 开头的,因此 sscanf() 正在查找输入字符串中的 4 个字母。未能找到这些,扫描停止,将double2 保留为之前的值。因此检查 sscanf() 结果的重要性。谁知道文件和标准输入中有哪些邪恶数据?

标签: c scanf


【解决方案1】:

改变

"%4[^,],%4[^,],%lf[^,],%lf[^\n]"

int result;
result = sscanf(buffer, "%4[^,],%4[^,],%lf,%lf", string1, string2, &double1, &double2);
if (result != 4) // handle error

注意double1double2 上的& - 可能是一个错字。

另外强烈建议检查结果是否为 4。不检查 sscanf() 结果确实是这个问题的核心。打印出的“零”是double2 未被扫描并保留其先前值的结果,该值可能是任何值。如果检查了sscanf() 结果,它会报告3,表明问题在扫描double1double2 之间。但在更大的场景中,最好在继续之前验证所有预期值都已扫描。

【讨论】:

    【解决方案2】:

    除非您的变量 double1double2 是指针,否则您将获得未定义的行为。

    您需要使用地址运算符& 来获取指向这些变量的指针:

    sscanf(buffer, "%3s,%3s,%lf,%lf", string1, string2, &double1, &double2);
    

    【讨论】:

      【解决方案3】:
      sscanf(buffer, "%4[^,],%4[^,],%lf[^,],%lf[^\n]", string1, string2, double1, double2);
      

      应该是

      sscanf(buffer, "%3s,%3s,%lf,%lf", string1, string2, &double1, &double2);
      

      注意&(地址)用于双打

      【讨论】:

        【解决方案4】:

        您的代码不起作用的原因是:

        sscanf(buffer, "%4[^,],%4[^,],%lf[^,],%lf[^\n]", string1, string2, &double1, &double2);
        

        %[...]%[^...] 实际上是转换类型,如%d%x,它们匹配/不匹配列出的字符序列,以] 结尾。请注意,您不必提供%s,即使您正在解析字符串。

        您的问题是您结合了两种类型的转换类型,%lf[^...],scanf 实际上将后面的部分视为要匹配的字符串,因此例如以下代码将成功解析字符串:

        char *b = "ABC,DEF,0.465798[^,],0.754314[^\n]\n";
        sscanf(b, "%4[^,],%4[^,],%lf[^,],%lf[^\n]", string1, string2, &double1, &double2);
        

        最简单的解决方案是留下[^,]部分(chux的解决方案):

        sscanf(b, "%4[^,],%4[^,],%lf,%lf", string1, string2, &double1, &double2);
        

        或使用字段宽度(Joachim Pileborg 和 David RF 的解决方案):

        sscanf(buffer, "%3s,%3s,%lf,%lf", string1, string2, &double1, &double2);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多