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。
你可以想象这就像有两个独立的控制台,一个用于输入,另一个用于输出。
例如,您要为 a
和 3 输入 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);
}
我从来没有用 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。
你可以想象这就像有两个独立的控制台,一个用于输入,另一个用于输出。
例如,您要为 a
和 3 输入 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);
}