我有一个递归函数,它使用
printf()
和 scanf()
来处理用户输入。如果用户不小心按错了键(不是“y”),它会循环返回。但是,如果用户输入多个字符,该函数会要求用户一次输入多次。 printf()
行的重复次数与输入中的字符一样多。
为什么终端缓冲区中的字符过多会导致这种行为,而不是整个事情崩溃或终端只是忽略以下字符?
int testDetectorWhite(){
char userConfirmation;
printf("Please place a WHITE disk directly below the detector\n");
printf("Press 'y' when ready:\n");
scanf("%c", &userConfirmation);
printf("\n");
if(userConfirmation != 'y'){
testDetectorWhite();
}
//more code
}
我尝试重写代码,用递归 if() 代替 while() 循环,如下所示:
while(userConfirmation != 'y') {
printf("Please place a WHITE disk directly below the detector\n");
printf("Press 'y' when ready:\n");
scanf("%c", &userConfirmation);
}
但是,我仍然遇到完全相同的错误。
我尝试通过使
userConfirmation
成为一个字符串来解决问题,这解决了多个 printf()
函数运行的问题,但导致了更多超出我的问题范围的问题。
你有两个问题,都与
scanf
功能及其许多不足有关。
"%c"
无法按预期工作。您需要使用" %c"
,其中有一个额外的空间。参见 scanf() 在缓冲区中留下换行符 .scanf
不是一个好的选择。一般来说,问题是“坏”输入往往会留在输入流中,未读,这意味着您可能不得不尝试以某种方式“刷新”它。另见如何在 fgets 循环中正确刷新标准输入和使用 fflush(stdin).一般来说,如果你想让用户键入表单 A 的输入,但又担心用户可能会键入表单 B 的输入,你必须让用户键入,并且你必须读入,即表单 B 的输入。 您不能只编写代码来尝试读取表单 A 的输入,希望表单 B 的输入会被神奇地丢弃。 例如,正如您在此处看到的,如果您编写的代码在循环中使用
%c
读取单个字符,而用户错误地键入了三个字符,则您的循环将运行三次。
所以在一般情况下,如果你想处理用户可能错误地输入任何随机形式 B 而不是你想要的输入的情况,你最终不得不将用户的输入读取为 string,使用
scanf %s
,或者fgets
。然后你必须检测输入是否是你想要的形式(“形式 A”)。然后您可能必须将输入转换为您想要的形式(例如,从字符串转换为单个字符,或从字符串转换为整数)。
无可否认,这是要做的更多工作,而且有点麻烦。如果您刚刚起步,我建议您专注于正确的输入,也就是说,编写代码时假定用户永远不会输入任何错误的内容。显然,从人为因素的角度来看,检测错误的输入是很好的,打印一个很好的提示要求用户再试一次,但是正确地编码却非常困难!这是一个你可能想推迟几周的问题,同时你会了解更多关于解决它所需的其他 C 工具。