这是我正在做的一小部分练习,可以防止错误的输入。
while(1) {
printf("Choose From 1 to 7 ");
if( scanf("%d", &nNum ) != 1) {
printf("Please only choose from the numbers 1-7.");
fgets(sErraticInputs, 100 , stdin);
} else if (nNum > 7 || nNum <= 0) {
printf("Please only choose from the numbers 1-7.");
} else {
break;
}
}
我做得很好,直到我输入“6; p”。它执行了6部分并正确运行,但从技术上讲它应该将整个事情作为输入,然后继续输入错误消息。
答案 0 :(得分:1)
首先,我不认为发布的代码可以提供上述结果。当break
被读取时,while(1)
语句将结束6
,因此不会打印错误消息。
如果我们假设break
不是您真实代码的一部分,则会发生以下情况:
当告诉scanf
读取整数时,只要下一个字符(与先前读取的字符一起)可以转换为整数,它就会继续从输入流中读取。一旦下一个字符不能用作整数的一部分,scanf
将停止并为您提供到目前为止已解析的结果。
在您的情况下,输入流包含
6;p\n
因此scanf
会读取6
并停止(即返回6
)。输入流现在包含:
;p\n
因此,这将是您下一个scanf
的输入,并导致输入错误,您看到了。
解决这个问题的一种方法是在所有 scanf
之后刷新标准输入 - 无论是成功还是失败:
nNum = 0;
while(nNum != 7) // Just as an example I use input 7 to terminate the loop
{
printf("Choose From 1 to 7 ");
if( scanf("%d", &nNum ) != 1 || nNum > 7 || nNum <= 0)
{
printf("Please only choose from the numbers 1-7.");
}
else
{
printf("Valid input %d\n", nNum);
// **************************** break;
}
fgets(sErraticInputs, 100 , stdin); // Always empty stdin
}
注意:使用大小为100的fgets
并不能确保完全刷新...您应该实际使用循环并继续直到读取'\n'
。
如上所述,6;p
之类的输入将被视为值为6的有效输入,而p将被丢弃。
如果这不可接受,您可以放弃使用scanf
并自行解析。有几种选择,例如fgets
或fgetc
以下示例使用fgetc
#include <stdio.h>
#include <stdlib.h>
int get_next()
{
int in = fgetc(stdin);
if (in == EOF) exit(1); // Input error
return in;
}
void empty_stdin()
{
while(get_next() != '\n') {};
}
int main(void) {
int in;
int nNum = 0;
while(nNum != 7)
{
printf("Choose From 1 to 7 \n");
in = get_next();
if (in == '\n' || in <= '0' || in > '7') // First input must be 1..7
{
printf("Please only choose from the numbers 1-7.\n");
if (in != '\n') empty_stdin();
}
else
{
nNum = in - '0';
in = get_next();
if (in != '\n') // Second input must be \n
{
printf("Please only choose from the numbers 1-7.\n");
empty_stdin();
}
else
{
printf("Valid input: %d\n", nNum);
}
}
}
return 0;
}
此代码只接受一个数字(1..7)后跟换行符
答案 1 :(得分:0)