【问题标题】:C fscanf input validationC fscanf 输入验证
【发布时间】:2016-04-28 17:19:47
【问题描述】:

我正在使用带有 fscanf 的 for 循环将文件中的 5 列输入到结构数组中。每个结构有 5 个变量:1 个字符串和 4 个整数,第一个 fscanf 读取字符串名称并将其存储为将其他 4 个输入整数构造到所述结构中(全部指向结构的不同变量)。使用正常输入它工作正常。但是当一个字符被输入到整数列之一时,scanf 将 0 和该结构的其余值放入并使用 char 就好像它是一个新结构一样,即它跳过它之后的所有内容并使用不需要的 char 作为名称将行的剩余值作为其输入。 我的问题是,是否有一种方法可以忽略该输入生成的不需要的结构,或者有一种方法可以简单地防止识别字符并跳过特定的 scanf? 我尝试使用 fgets 而不是 scan 但它不起作用,而且我不能使用 0 来整理不需要的值,因为 0 可以作为正常值输入。 我理解理想情况下查看代码会有所帮助,但出于抄袭的原因,我不想发布它,因为这是针对大学的,我不渴望那些抄袭会议。 如果问题没有得到很好的解释,请提前致谢。 :)

【问题讨论】:

  • fscanf() 函数真的很难正确使用,特别是用于输入验证。也就是说,请阅读它的返回值。

标签: c struct


【解决方案1】:

您需要检查fscanf()的返回值以确保它成功,如果它失败它不会修改超出失败说明符的参数

char name[100];
int value1;
int value2;
int value3;
int value4;

if (fscanf(file, "%99s%d%d%d%d", name, &value1, &value2, &value3, &value4) == 5)
    success();
else
    failure();

当然,success()failure() 实际执行的操作取决于您,但这样可以防止未定义的行为。

【讨论】:

    【解决方案2】:

    关键是“输入 5 列”,这意味着 的文本。使用fscanf() 同步具有挑战性,特别是如果您想以其他方式解释文本。最好分开处理读取和解析。

    char buf[100];
    while (fgets(buf, sizeof buf, istream)) {
      char s[sizeof buf];
      s[0] = 0;
      int i[4] = { 0,0,0,0 }; // default values
    
      // c is the count of scanned variables
      int c = sscanf(buf, "%s%d%d%d%d", s, &i[0], &i[1], &i[2], &i[3]);
    
      printf("%d: %s %d %d %d %d\n", c, s, i[0], i[1], i[2], i[3]); 
    }
    

    " 但是当一个字符输入到整数列之一时,scanf 为那个 " 放置 0 可能是错误的。您看到的是以前的值。

    【讨论】:

      【解决方案3】:

      简短的回答是,fscanf 是这个工作的错误工具。

      我猜这是你想要阅读的文件类型:

      abc 1  2  3  4
      def 5  6  7  8
      ghi 9 10 11 12
      

      因此,即使您有完美代码来使用fscanf 读取此数据,由于fscanf 的工作方式,您的代码也可以完美地读取这个看起来很垃圾的文件,创建相同的三个记录:

      abc 1  2  3   4 def
      5   6  7  8 ghi 9
      10 11 12
      

      读取格式化文本行的更好方法是使用fgets 一次读取一行,然后将每一行分解为其字段。

      我,我总是使用一个名为getargs 的函数,它在argcargv 中将一行分成以空格分隔的“单词”,就像main() 接收一样。不幸的是getargs 不是标准的。但是您可以使用these class notes 中描述的版本。

      您可以使用标准库函数strtok 或多或少地做同样的事情。 (很遗憾我不能告诉你怎么做,因为我从来不用strtok。)

      最后,您可以使用 sscanf,正如 chux 已经建议的那样。您说您已经尝试过,但它“没有用”,但如果您提供更多详细信息,我们或许可以帮助您使其正常工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-29
        • 1970-01-01
        • 2020-09-06
        • 2012-11-02
        • 2012-10-11
        • 2016-10-07
        • 1970-01-01
        相关资源
        最近更新 更多