C 无限循环扫描函数
我正在学习c语言,并且理解这种语言是低级的,在这种情况下缺乏异常处理 我制作了一个简单的程序,用户可以从菜单中选择一些选项。就这么简单 程序分为几个方法-其中一个方法等待用户按键-需要一个整数。然后将这个整数返回给另一个保存开关结构的方法 当按下一个字符时,问题就出现了——在大多数情况下,else块的无限循环被启动 您必须选择一个备选方案0-2。请重试:-) 您必须选择一个备选方案0-2。请重试:-) 您必须选择一个备选方案0-2。请重试:-) 。。。。。。等等 我实际上不知道如何解决这个问题。我尝试使用scanf函数的返回值,但没有成功。我还尝试将一个字符(而不是整数)作为参数传递给scanf函数,但也没有成功 如何处理这个问题有什么建议吗C 无限循环扫描函数,c,scanf,C,Scanf,我正在学习c语言,并且理解这种语言是低级的,在这种情况下缺乏异常处理 我制作了一个简单的程序,用户可以从菜单中选择一些选项。就这么简单 程序分为几个方法-其中一个方法等待用户按键-需要一个整数。然后将这个整数返回给另一个保存开关结构的方法 当按下一个字符时,问题就出现了——在大多数情况下,else块的无限循环被启动 您必须选择一个备选方案0-2。请重试:-) 您必须选择一个备选方案0-2。请重试:-) 您必须选择一个备选方案0-2。请重试:-) 。。。。。。等等 我实际上不知道如何解决这个问题。
#include <stdio.h>
#include <stdlib.h>
void menu();
void runSelection(int selection);
int getSelection();
int pause();
int main(void) {
do{
menu();
runSelection(getSelection());
}while(pause());
return 0;
}
int pause() {
int c;
printf("\n\nPress enter to continue!");
fflush(stdout);
/* flush inputstream */
while((c = getchar()) != '\n' && c != EOF);
getchar();
return 1;
}
void menu() {
puts(" * * * * * * M E N U * * * * * * *");
puts("1. Do something 1");
puts("2. Do something 2");
puts("3. Do something 3");
fflush(stdout);
}
void runSelection(int selection) {
switch (selection) {
case 0:
puts("you pressed 0");
break;
case 1:
puts("you pressed 1");
break;
case 2:
puts("you pressed 2");
break;
}
}
int getSelection() {
int key;
int true = 0;
do {
scanf("%d", &key);
if (key >= 0 && key <=2) {
true = 1;
}
else {
puts("You must choose an alternative 0 - 2. Please try again :-)");
fflush(stdout);
}
} while (true == 0);
return key;
}
#包括
#包括
无效菜单();
无效运行选择(int选择);
int getSelection();
int pause();
内部主(空){
做{
菜单();
运行选择(getSelection());
}while(暂停());
返回0;
}
int pause(){
INTC;
printf(“\n\n按enter继续!”);
fflush(stdout);
/*刷新输入流*/
而((c=getchar())!='\n'&&c!=EOF);
getchar();
返回1;
}
无效菜单(){
看跌期权(“********M E N U********”);
放置(“1.做某事1”);
放置(“2.做某事2”);
放置(“3.做某事3”);
fflush(stdout);
}
无效运行选择(整数选择){
开关(选择){
案例0:
放置(“您按下了0”);
打破
案例1:
放置(“您按下1”);
打破
案例2:
放置(“您按了2”);
打破
}
}
int getSelection(){
int键;
int真=0;
做{
scanf(“%d”和键)(&key);
如果(key>=0&&key您得到一个无限循环,因为scanf正在从输入缓冲区读取一个字符。缓冲区中还有一个剩余字符,换行符'\n'
使用以下宏,而不是直接使用scanf
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
int main()
{
int decision;
printf("Input data, valid choice 1 or 0: ");
SCAN_ONEENTRY_WITHCHECK("%d",&decision,(decision==0 || decision==1));
printf("You have entered good input : %d\n", decision);
}
以下主题包含有关此宏以及如何使用它的说明:
为什么没有像其他地方一样删除getSelection
中的尾部'\n'
使用:
在getSelection
too编辑:当我第一次写这个答案时,我是如此愚蠢,对scanf()
的工作原理一无所知
- 首先让我澄清一点,
scanf()
不是一个坏函数,如果我不知道scanf()
如何工作并且我不知道如何使用它,那么我可能没有阅读scans()
的手册,这不可能是scanf()
的错
- 其次,为了理解代码的错误,您需要了解
scanf()
的工作原理
在代码中使用scanf(“%d”,&key)
时,scanf(
)尝试从输入中读入整数,但如果输入非数值,scanf()
知道它不是正确的数据类型,因此它会在下一个循环周期将读取输入放回缓冲区,但无效输入仍在缓冲区中,这将导致scanf()
再次失败,因为缓冲区尚未清空,而此循环将永远持续下去
为了解决这个问题,可以使用scanf()的返回值
,这将是成功读取的输入数,但是您需要通过刷新缓冲区来丢弃无效输入,以避免无限循环,当按下enter
键时,输入缓冲区将被刷新,您可以使用getchar()执行此操作
函数暂停以获取输入,这将要求您按enter键,从而丢弃无效的输入。请注意,无论您是否输入了正确的数据类型,这不会使您按两次enter键,因为换行符仍将在缓冲区中。在scanf()之后
已成功从输入中读取整数,它将把\n
放回缓冲区,因此getchar()将读取它,但由于您不需要它,因此可以安全地丢弃它:
do
{
status = scanf("%d", &key);
getchar(); // flush the buffer by reading a character and discarding it
if (key >= 0 && key <=2)
{
true = 1;
}
else
{
puts("You must choose an alternative 0 - 2. Please try again :-)");
fflush(stdout);
}
} while (true == 0 && status != 1);
do
{
status=scanf(“%d”和键)(&key);
getchar();//通过读取字符并丢弃它来刷新缓冲区
如果(键>=0&&key
do
{
status = scanf("%d", &key);
getchar(); // flush the buffer by reading a character and discarding it
if (key >= 0 && key <=2)
{
true = 1;
}
else
{
puts("You must choose an alternative 0 - 2. Please try again :-)");
fflush(stdout);
}
} while (true == 0 && status != 1);