scanf returns 0 不等待输入

Scanf returns 0 without waiting for input

我从来没有用 C 编程过,今天我必须写一些小代码。程序非常简单——我想添加两个整数。 但是当我试图检查给定的输入是否是一个数字时,第一个 scanf returns 0,第二个 returns 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;
}

那是因为,一旦第一个scanf()失败,很可能是因为匹配失败,而导致匹配失败的输入,则保留在输入缓冲区中,等待下一次调用消耗。

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

解决方法:第一次输入失败scanf()后,你必须清理输入缓冲区,举个简单的例子,比如while (getchar() != '\n');应该完成这项工作。

这是因为在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

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


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

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

第一个 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;
}

您可以使用字符串做同样的事情,而不会出现 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);
}