while循环在获取getchar()之前重复printf两次?

我目前正在学习C和C ++。 在这个小小的“程序实践”中,我要求用户输入’i’或’d’来知道他们是想使用整数还是十进制(浮点数)。 我有一个while循环,通过告诉他们输入错误的char来确保用户输入’i’或’d’。 出于某种原因,while循环内的提示在进入getchar()之前打印两次。 在这种情况下,我有点难以理解幕后发生的事情。 任何帮助都非常感激。 我正在使用Xcode(不知道它是否相关)。

#include  int main() { char action; printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n"); scanf("%c", &action); while (action != 'i' || action != 'd') { printf("You didn't entered the right command. Please try again (i/d)\n"); action = getchar() } } 

所以我得到的输出是这样的:

 You didn't entered the right command. Please try again (i/d) You didn't entered the right command. Please try again (i/d) 

发生的事情是当你输入一个角色并点击一个回归时,你实际上输入了两个字符 – 字符和返回字符(’\ n’)。 循环对每个字符执行一次。 这就是为什么你看到它经历了两次。

诀窍是明确过滤掉返回字符,如下所示:

 #include  int main() { char action; printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n"); scanf("%c", &action); while (action != 'i' || action != 'd') { if (action != '\n') { printf("You didn't entered the right command. Please try again (i/d)\n"); } action = getchar(); } } 

正如Ziffusion在他的回答中正确诊断的那样 ,你会得到双提示,因为在用户输入不正确的单独字符后得到换行符,这也不是id

这是一个改写,有一些改进:

 #include  int main(void) { char action = '\0'; printf("Please enter 'i' to work with integers or 'd' to work with decimals: "); while (scanf(" %c", &action) == 1 && action != 'i' && action != 'd') printf("You didn't enter the right command. Please try again (i/d): "); printf("Action selected: %d\n", action); } 

有什么改变?

  1. 提示不以换行符结束,因此用户的响应会立即显示在其后面。 标准I / O通常会同步标准输出和标准输入,以便刷新提示,尽管不以换行符结束。 如果没有出现提示,可以添加fflush(stdout);fflush(0); 在每个提示printf()语句之后。

  2. 检查scanf()的结果以处理EOF。

  3. scanf()的格式包括前导空格。 这将在返回的字符之前跳过空格,因此您将获得非空白的非换行符。

  4. 最初的条件action != 'i' || action != 'd' action != 'i' || action != 'd'永远是真的; 你需要&&代替。

  5. Nitpick:改进错误信息的语法。

请注意,在循环之后,如果用户触发了EOF(键入的Control-D或等效的),则操作可能不是id 。 如果你得到EOF(例如,用户使用/dev/null标准输入运行程序),除了初始化为'\0'之外,你不会有一个确定的值。

在这里我修复了你的代码:

 #include  int main() { char action; printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n"); scanf("%c", &action); while (action != 'i' && action != 'd') // here the loop will stop if action is 'i' or 'd' { printf("You didn't entered the right command. Please try again (i/d)\n"); scanf("\n%c", &action);// here to deal with '\n' } }