我们如何测试scanf()函数的返回值?

时间:2012-04-10 06:40:29

标签: c scanf

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

2 个答案:

答案 0 :(得分:12)

scanf()等返回成功转化的次数。

如果你有:

scanf("%f", &f);

你应该测试:

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

如果您有多次转化,请检查它们是否全部完成。如果您使用的是%n'转化',则不会计算在内。

虽然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()甚至是{{1}等函数}和strtol()从行中读取特定值。如果您使用strtod(),则上述有关检查成功转化次数的评论仍然适用。

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

答案 1 :(得分:5)

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

  

这些函数成功返回输入项的数量   匹配          和分配,可以少于提供,甚至零          早期匹配失败的事件。

     

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

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

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