Scanf返回0而不等待输入

时间:2016-11-09 16:17:35

标签: c scanf stdin

我从未在C编程,今天我必须编写小代码。程序很简单 - 我想添加两个整数。 但是当我试图检查给定输入是否为数字并且第一个scanf返回0时,第二个也返回0而不等待输入。 代码:

int main()
{
    int a = 0;
    int b = 0;
    printf("Number a:\n");
    if (scanf("%d", &a) != 1)
    {
        printf("Not a number. a=0!\n");
        a = 0;
    }
    printf("Number b:\n");
    if (scanf("%d", &b) != 1)
    {
        printf("Not a number. b=0!\n");
        b = 0;
    }
    printf("%d\n", a+b);
    return 0;
}

4 个答案:

答案 0 :(得分:1)

这是因为,一旦第一个scanf()失败,可能是因为匹配失败,导致匹配失败的输入仍然在输入缓冲区内,等待下一次调用消耗。

因此,对scanf()的下一次调用也会尝试立即使用驻留在输入缓冲区中的相同无效输入,而不等待显式外部用户输入,因为输入缓冲区不是空。

解决方案: scanf()第一次输入失败后,您必须清理输入缓冲区,对于一个简单的示例,像while (getchar() != '\n');这样的事情应该可以完成。

答案 1 :(得分:1)

无法转换为第一个fscanf()的数字的输入在标准输入缓冲区中仍然未决,导致第二个fscanf()也失败。尝试丢弃违规输入并重新提示用户:

#include <stdio.h>

int main(void) {
    int a = 0;
    int b = 0;
    int c;
    printf("Number a:\n");
    while (scanf("%d", &a) != 1) {
        printf("Not a number, try again:\n");
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        if (c == EOF)
            exit(1);
    }
    printf("Number b:\n");
    while (scanf("%d", &b) != 1) {
        printf("Not a number, try again:\n");
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        if (c == EOF)
            exit(1);
    }
    printf("%d\n", a + b);
    return 0;
}

使用实用程序函数对代码进行分解使其更加清晰:

#include <stdio.h>

int get_number(const char *prompt, int *valp) {
    printf("%s:\n", prompt);
    while (scanf("%d", valp) != 1) {
        printf("Not a number, try again:\n");
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        if (c == EOF)
            return 0;
    }
    return 1;
}

int main(void) {
    int a, b;

    if (!get_number("Number a", &a) || !get_number("Number b", &b)) {
         return 1;
    }
    printf("%d\n", a + b);
    return 0;
}

答案 2 :(得分:0)

由于输入和输出未在C中同步,程序可以在用户输入后输出一些行,而输入尚未被读取。尝试运行此代码:

char token;

scanf("%c", &token);
printf("%c\n", token);
printf("line 1\n");

scanf("%c", &token);
printf("%c\n", token);
printf("line 2\n");

scanf("%c", &token);
printf("%c\n", token);
printf("line 3\n");

并在一行中输入 abc

你可以想象这就像有两个独立的控制台,一个用于输入,另一个用于输出。

例如,您要为a输入 asd ,为{{1}输入 3 }}。在这种情况下,第一个b不会找到任何数字并返回0.但它也不会从输入中读取任何内容。因此,第二个scanf也会看到 asd

如果scanf不是数字,要清除输入,您应该输入行中所有剩余的字符,直到a(查看@ Sourav&#39; s解决方案)

答案 3 :(得分:0)

您可以使用字符串执行相同的操作而不会出现scanf问题。只需将用户输入作为字符串并将其转换为整数。然后将字符串转换回整数以检查它们是否相同。如果它们是相同的,则将a和b视为整数,如果不是,则执行您的操作(您需要包含string.h)。这是工作代码:

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

int main()
{
int a;
int b;
char str1[100];
char str2[100];

printf("Number a:\n");  
scanf("%s", &str1); //take input as a string
a = atoi(str1); //convert string to integer
snprintf(str2, 100, "%d", a); //convert integer back to string

//if the integer converted to string is not the same as the string converted to integer
if (strcmp(str1, str2)!= 0)
{
printf("Not a number. a=0!\n");
a = 0;
}
printf("Number b:\n");
scanf("%s", &str1);
b = atoi(str1);
snprintf(str2, 100, "%d", b);

if (strcmp(str1, str2)!= 0)
{
printf("Not a number. b=0!\n");
b = 0;
}
printf("%d\n", a+b);

return(0);
}