当第一个跟踪失败时,为什么我不能再对同一个变量使用scanf

时间:2014-10-21 04:31:21

标签: c scanf

请参阅以下代码:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    int i = scanf("%d", &n);
    printf("%d\n", i);
    int j = scanf("%d", &n);
    printf("%d\n", j);
    return 0;
}

假设我第一次输入n的字符串,scanf将返回0;但是,为什么它不允许我第二次输入n的值而j是自动的0?我该怎么办才能让我再次为n输入一个值,即使我第一次键入了错误的值?

4 个答案:

答案 0 :(得分:4)

您几乎肯定会输入一个非数字值,这将导致第一个scanf失败,返回零并且(这是重要的一点)将流指针保持在之前的精确位置scanf来电。

这意味着您调用它的 next 时间,它只会尝试读取相同的数据。

零的返回值是一个死的赠品 - scanf返回成功扫描的项目数,所以零意味着你没有给它一个数字。

如果输入数字,则可以正常使用,如下代码所示:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    int i = scanf("%d", &n);
    printf(">> %d %d\n", i, n);
    int j = scanf("%d", &n);
    printf(">> %d %d\n", j, n);
    return 0;
}

当您运行并输入4132时,您会看到:

41
>> 1 41
32
>> 1 32

在他们职业生涯的某个阶段,每个C程序员都会遇到该语言中用户输入不足的问题。基于行的输入最好的选择是简单地找到一个能很好地运行的函数,然后在结果字符串上使用sscanf

确保行是基本单元,并且可以处理缓冲区溢出并确保过多的数据不会“破坏”未来的输入。

Here's one我之前准备过了。

答案 1 :(得分:1)

在重新输入输入并读取输入之前,您可以忽略其余部分。您可以使用以下方法忽略该行的其余部分:

scanf("%[^\n]*\n");

答案 2 :(得分:1)

如果您输入数字,您的代码将正常工作。但是,在输入字符串时,必须先从输入流中删除该字符串,然后再使用它。


例如:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int n;
    char c;
    int i = scanf("%d", &n);
    printf("%d\n", i);
    //Remove the previous string from the input stream
    while ( (c = getchar()) != '\n' && c != EOF );
    int j = scanf("%d", &n);
    printf("%d\n", j);
    return 0;
}

输入为整数时的输出

100
1
200
1

输入为字符串时的输出

abcd
0
efghi
0

供进一步参考:Why does everyone say not to use scanf? What should I use instead?

答案 3 :(得分:1)

您输入的非数字字符串不会被scanf使用。

相反,您可以像这样使用fgetssscanf

#include <stdio.h>

int main(void)
{
    int n;
    char str[100];
    fgets(str, sizeof(str), stdin);
    int i = sscanf(str, "%d", &n);
    printf("%d\n", i);
    fgets(str, sizeof(str), stdin);
    int j = sscanf(str, "%d", &n);
    printf("%d\n", j);
    return 0;
}