发生错误时Scanf返回1而不是0

时间:2019-11-27 21:37:10

标签: c input return scanf c99

我已经知道,返回的scanf值表明它是否能够成功读取和转换值。 我使用返回值来检测输入是否为整数,但是输入是否为4.5 scanf返回1,而输入为g scanf返回0 。 她是我的密码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x;
    int ReturnedValue=scanf("%d",&x);
    printf("Scanf Returned:%d",ReturnedValue);
    return 0;
}

在多篇不同的文章中,您建议使用返回的scanf值来检测整数,但是为什么现在不起作用?

5 个答案:

答案 0 :(得分:5)

返回值不表示成功或失败。这是成功转换的值的数量。

这就是为什么您以"%d"为格式在“ 4.5”上获得“ 1”,然后将“ 4”转换为

的原因。

通过阅读scanf()的文档,您会发现这一点。

答案 1 :(得分:3)

问题是scanf(或atoi)解析整数并不可靠。

在您的情况下,scanf找到4并对此感到满意,这说明了返回码1。

最安全的方法是使用strtolstrtoul ..基元,以确保 word 作为整数有效(有关更多详细信息,请检查{{3 }},答案是“不要使用scanf”顺便说一句:))

在您的特定情况下(粘在scanf上,您可以可以通过先扫描为 float (使用%f浮动变量)。并检查浮点值是否为整数

float xf;
if (scanf("%f",&xf) == 1)
{
     // one integer or float was scanned
     x = (int)xf;
     if (x==xf)
     {
        // scanned value is an integer: valid
     }
}

但是4XXXX之类的输入仍然会被错误地接受。如果您必须使用scanf,则必须承担一定程度的风险。

答案 2 :(得分:0)

  

我已经使用返回值来检测输入是否为整数,但是如果输入为4.5,则scanf返回1,如果输入为g,则scanf返回0。

在这种情况下,这实际上是有道理的。

int ReturnedValue = scanf(“%d”,&x);

记住scanf返回值是正确解析的项目数。

  • 如果输入4.5,它将仅读取第一个数字4并正确解释int值。它将丢弃输入中所有剩余的无效字符。

  • 如果输入d,则scanf完全失败(它无法解析任何int),因此返回0。

请参阅scanf手册-了解为什么将4.5解析为整数4:

  

在达到此最大值时,字符的读取将停止                 已到达或找到不匹配的字符                 首先发生。

http://man7.org/linux/man-pages/man3/scanf.3.html

答案 3 :(得分:0)

最初,我不想写答案,只留下评论。我想要 扩展Jean-François Fabre的答案。

scanf家庭的问题在于他们没有做大多数人做的事 相信他们这样做,然后就为何这样做“奇怪”感到困惑。实际上,他们根据格式扫描输入并为 变量(通过指针传递)。当他们遇到错误时,即某事 与格式不匹配,然后它们停止。

使用"%d"格式,您只是说要读一个整数。格式不 说“读一个整数,只有一个整数”。为此,您还需要 排除其他所有内容,如果我没有记错的话,那将是 "%d[^0-9]*"(我没有测试过是否正确)。 这就是为什么用户输入4.5scanf。请注意,scanf的操作不正确,是您在指定它 错误地,因为您假设"%d"的意思是“以及整数和整数 唯一”。

如您所见,很难找到一种可以捕捉的格式 一切,还告诉您用户何时出错。用户输入又名什么 用户输入的内容是随机的,可能包含(无意间)错误,请 格式等。因此,您最终会得到非常复杂的格式,只能确定 用户在末尾添加了一个点,如果这样做则失败。

这就是为什么我的建议是通过fgets阅读while输入,然后使用更好的东西 如果格式良好,则可以解析strtol甚至sscanf之类的输入。

以下是strtol用法的示例:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    const char *entries[] = { "4.5", "4", "some random text" };
    char *ptr;

    int i;
    for(i = 0; i < sizeof entries / sizeof *entries; ++i)
    {
        long int res = strtol(entries[i], &ptr, 0);

        if(*ptr != '\0') {
            printf("The input '%s' is not an integer. The non-integer is '%s'\n", entries[i], ptr);
        } else {
            printf("The input '%s' is an integer: %ld\n", entries[i], res);
        }
    }

    return 0;
}

返回

The input '4.5' is not an integer. The non-integer is '.5'
The input '4' is an integer: 4
The input 'some random text' is not an integer. The non-integer is 'some random text'

这是检查整个输入是否为整数的更精确的方法。

答案 4 :(得分:0)

  

发生错误时,Scanf返回1而不是0

输入中未发生错误。第一个字符"4"可以很好地转换为4。代码需要检查其余部分。

  

我被迫在拼贴中使用scanf

不幸的是,这种编码约束。 fgets()/strtol()会更好。

  

如何在不破坏c整个代码的情况下,以简单快速的方式检测它是否为整数?

扫描整数并查找结尾的垃圾。

char endchar;  
int cnt = scanf("%d%c",&x, &endchar);
if (cnt == EOF) puts("End-of-file occurred");
else if (cnt == 1 || (cnt == 2 && endchar == '\n')) printf("Success %d\n", x);
else puts("Non-integer input");

当数据为非整数输入时,stdin中可能会保留一些有问题的字符。因为此任务只是读取一个int,所以可以。

生产代码更有可能读取然后对其进行解析。