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

Kaw*_*iKx 4 c scanf

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

Jon*_*ler 14

scanf() 等人返回成功转换的次数.

如果你有:

scanf("%f", &f);
Run Code Online (Sandbox Code Playgroud)

你应该测试:

if (scanf("%f", &f) == 1)
    ...all OK...
else
    ...EOF or conversion failure...
Run Code Online (Sandbox Code Playgroud)

如果您有多次转换,请检查它们是否已完成.如果您使用%n"转化次数",则不计算在内.

尽管scanf()确实在EOF上返回EOF,但您不应该对此进行测试 - 您应该始终检查您是否获得了预期的转换次数.例如,考虑有缺陷的代码:

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

如果你键入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...
}
Run Code Online (Sandbox Code Playgroud)

从前面的问题来看,你应该考虑使用fgets()(或可能POSIX getline())读取数据的线,然后使用sscanf()甚至功能,如strtol()strtod()读取来自行特定的值.如果您使用sscanf(),上面提到的关于检查成功转换次数的评论仍然适用.

我没有scanf()在生产代码中使用; 真是太难控制了.我认为它几乎适合开始程序 - 除了它引起很多混乱.就整体而言,最好的建议是"留下清晰的scanf()fscanf()".请注意,这并不意味着您必须保持清醒sscanf(),尽管需要谨慎一些sscanf().


Aus*_*oke 5

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

这些函数返回成功匹配和分配的输入项的数量,这可以少于提供的数量,或者在早期匹配失败的情况下甚至为零.

如果在第一次成功转换或匹配失败发生之前达到输入结束,则返回值EOF.如果发生读取错误,也会返回EOF,在这种情况下,将设置流的错误指示符(请参阅ferror(3)),并设置errno指示错误.

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

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