【问题标题】:How do we test the return values from the scanf() function?我们如何测试 scanf() 函数的返回值?
【发布时间】:2012-04-10 06:40:29
【问题描述】:

我想确认scanf() 函数返回的值是否为浮点数。我怎样才能做到这一点?如果向scanf() 函数提供了错误的数据类型,我的代码将无法正常运行。同样,如何确认返回的值是否为字符串?

【问题讨论】:

  • 我见过的scanf的所有版本,返回一个int
  • @Saurabh 按照你之前的 Qn,我想你想知道 scanf 是否成功扫描了一个浮点数,而不是 它的返回值是否是一个浮点数 如您的问题所述?
  • 对于*scanf() 系列函数,最重要的一点可能是如果您扫描一个数值超出相应类型范围的数字,则行为未定义。例如,如果scanf("%d") 尝试读取999999999999999999999,任何事情都可能发生;没有办法处理错误。除了使用*scanf() 以外的其他东西(例如strto*() 函数)之外,没有其他好的解决方法。
  • 即使使用strtol() 等函数,测试错误也不是一件容易的事。仔细阅读规范。然后再读几遍。
  • @PavanManjunath 是的,除了 printf 和 scanf 之外,我还没有了解任何其他功能。所以我很难遵循以前的答案。我所能收集到的只是一个函数并不是针对所有可能错误的万无一失的解决方案。通过这个问题,我希望了解如何改进我以前包含 scanf 的代码。

标签: c scanf


【解决方案1】:

scanf() et al 返回成功转换的次数。

如果你有:

scanf("%f", &f);

你应该测试:

if (scanf("%f", &f) == 1)
    ...all OK...
else
    ...EOF or conversion failure...

如果您有多个转换,请检查它们是否都已完成。如果您使用的是 %n 'conversions',则不会计算在内。

虽然scanf() 确实在 EOF 上返回 EOF,但您不应该对此进行测试 - 您应该始终首先检查您是否获得了预期的转化次数。例如,考虑错误代码:

while (scanf("%f %d %s", &f, &i, s) != EOF)  // Here be BUGS!
    ...loop body...

如果您输入3.14 x23 yes,那么您将有一个无限循环,因为scanf() 将在第一次迭代时返回 1(它成功转换为 3.14),然后返回 0(不是 EOF)。

你可能会接受:

while ((rc = scanf("%f %d %s", &f, &i, s)) != EOF)
{
    if (rc != 3)
        ...oops data problems...
    else
        ...all OK...
}

从前面的问题来看,你应该考虑使用fgets()(或者可能是POSIX getline())来读取数据行,然后使用sscanf()甚至像strtol()strtod()这样的函数来读取该行的特定值。如果你使用sscanf(),上面关于检查成功转换次数的cmets仍然适用。

我不在生产代码中使用scanf();实在是太难控制了。我认为它几乎适合开始程序——除了它会引起很多混乱。总的来说,最好的建议是“远离scanf()fscanf()”。请注意,这并不意味着您必须远离sscanf(),尽管即使使用sscanf() 也需要谨慎。

【讨论】:

  • 很棒的答案!但我有一个疑问:char a; scanf("%c", &a); 会返回零吗?
  • 如图所示,"%c" 不应该返回 0,因为要么有一个字符要读取,所以结果将为 1,或者没有任何内容可读取,因此结果将是 EOF。您仍然需要检查这两个选项中的哪一个适用,并且使用 if (scanf("%c", &a) == 1) { …got a char… } 仍然是正确的,这是主要答案中推荐的。
【解决方案2】:

scanf 的返回值表示成功读取并分配给您的变量或 EOF 的项目数:

这些函数成功返回输入项的数量 匹配的 和分配,它可以比规定的要少,甚至为零 早期匹配失败的事件。

如果在任何一个之前到达输入的结尾,则返回值 EOF 发生第一次成功转换或匹配失败。 EOF 是 如果发生读取错误也返回,在这种情况下错误指示符 为流(参见 ferror(3))设置,并且设置了 errno 指示 错误。

如果scanf 返回的int 的值小于格式字符串中输入说明符(或至少需要传递参数的说明符)的数量,那么您可以假设出现问题。

但是,如果您想对浮点数执行更彻底的验证,则应考虑使用strtod()。 IE。对于输入"1.23abc"scanf 会将1.23 存储到您的变量中并告诉您一切顺利,但是使用strtod 您可以检查最后转换的字符是否实际上是正在解析的字符串的结尾。

【讨论】:

    猜你喜欢
    • 2019-12-11
    • 2016-12-26
    • 2017-02-04
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 2019-12-14
    相关资源
    最近更新 更多