基本上,我需要确保input是一个整数,如下所示:
do {
printf("Enter > ");
scanf("%d", &integer);
} while (/* user entered a char instead of an int */);
我尝试过各种方法,但当我尝试输入char
时,总是以运行时错误或无限循环结束。我知道fflush(stdin)
是未定义的行为,最好不要在我的代码中涉及它,以防止任何错误,加上由于某些原因,它在VS2015中不再工作。
下面的代码是我尝试过的方法:
typedef enum {false, true} bool;
int ipt;
char c;
bool wrong_ipt;
do {
c = '\0';
printf("Enter > ");
scanf("%d%c", &ipt, &c); //infinite loop occurs while a char has been entered
} while (c != '\n');
do {
c = '\0';
printf("Enter > ");
} while (scanf("%d", &ipt) != EOF);
do {
wrong_ipt = false;
do {
ipt = NULL;
printf("Enter > ");
scanf("%d", &ipt);
if (ipt == NULL) {
wrong_ipt = true;
break;
}
} while (ipt == NULL);
} while (wrong_ipt);
当用户在C中输入char
时,除了fflush(stdin)
之外,是否还有其他方法可用于防止无限循环?
谢谢
5条答案
按热度按时间oxcyiej71#
问题是"scanf()"可能会在输入缓冲区中留下未读的数据,因此出现了"无限循环"。
另一个问题是您应该验证
scanf()
的返回值。如果您期望一个整数值...而scanf返回"0"个读取项...则您知道出了问题。下面是一个例子:
输出示例:
"希望能有所帮助!
rryofs0p2#
这是一个很好的例子,说明了为什么
scanf
通常不应该用于用户输入。由于用户输入是基于行的,因此可以预期输入函数总是一次读取一行输入。但是,函数
scanf
的行为方式并非如此。相反,它只使用与%d
转换格式说明符匹配所需的字符数。如果scanf
无法匹配任何内容,则它根本不使用任何字符。这样,下一次对scanf
的调用就会因为完全相同的原因而失败(假设使用了相同的转换说明符,并且您没有显式地丢弃无效的输入)。在撰写本文时,其他三个答案通过检查
scanf
的返回值并显式丢弃无效输入来解决这个问题。这些答案中的(!)个具有这样的问题:它们例如接受"6sdfj23jlj"
作为数字6
的有效输入,尽管在这种情况下,整行输入显然应该被拒绝,这是因为scanf
,如前所述,不会一次读取一行输入。因此,解决这个问题的最佳方案可能是使用基于行的输入
fgets
,这样,您将总是一次只读取一行输入(假设输入缓冲区足够大,可以存储一整行输入)。读取该行之后,可以尝试使用strtol
将其转换为数字。即使转换失败,输入行将从输入流中被消耗掉,因此您将不会遇到上面描述的大多数问题。使用
fgets
的简单解决方案如下所示:注意
goto
语句通常不应该使用,但是在这种情况下,为了跳出嵌套循环,它是必要的。此程序具有以下输出:
但是,这段代码还不完善,它还存在以下问题:
1.如果用户在一行中输入了100个字符,那么整行将无法放入输入缓冲区,在这种情况下,需要两次调用
fgets
来读取整行,程序将错误地将该行视为两个单独的输入行。1.代码不会检查用户输入的数字是否可以用
long
表示(例如,数字是否过大),函数strtol
通过相应地设置errno
来报告这一情况(这是scanf
所缺少的功能)。这两个问题也可以通过执行额外的检查和错误处理来解决。但是,代码现在变得如此复杂,以至于将其全部放入自己的函数中是有意义的:
gstyhher3#
你的根本错误在于你从来没有告诉你的程序去消耗无效的输入。用语言来说,你告诉程序:
我猜你以为你做的是
所以你需要做的就是重写你的代码,让它做你想做的事情(或者像另一个答案一样,想出一些其他的方法),也就是说,把你的程序写成:
您可能会发现一些有用的相关函数是
fgets
、sscanf
和atoi
。例如,如果你打算阅读一行输入,确保你 * 确实这样做了 *,而且 * 正确 *。许多人都很懒,如果行很长,他们就会做错事情;例如,仅读取行的一部分,或导致缓冲区溢出)monwx1rj4#
格式说明符%d告诉
scanf
在命令行中需要一个整数值。当用户输入一行数据时,它被读取为字符串,然后scanf
尝试了解输入的字符串是否可以解释为整数的十进制数字。如果解释成功,那么找到的值将存储在作为参数传递的整型变量中。
scanf
所做的rigth替换的次数由该函数以int
值的形式获取,因为您只期望一个输入,值1将指示一切正常。因此,如果出现错误,例如用户输入了一个无效的整数,
scanf
返回的数字小于格式说明符的数量。在这种情况下,小于1的值表示发生了错误:uurv41yg5#
我知道我回答这个问题有点晚了,但是您可以减少循环的使用,而使用jump语句,然后只使用一个if语句来检查错误的输入,仍然可以获得相同的结果