C语言中使用scanf/getchar从标准输入读取单个字符时失败了。

6
作为作业的一部分,我正在尝试从标准输入中读取一个字符,并根据它采取相应的行动:
char choice;

while (1) {
    printf("please enter [y]es, [n]o or [m]aybe: ");
    scanf("%c", choice);
    fflush(stdin);
    // validate input
    if (choice == 'y' || choice == 'n' || choice == 'm') {
        break;
    } else {
      printf("Please enter only \'y\', \'n\' or \'m\'!\n");
    }
}
// do something with the input
if (choice == 'y') {
    printf("you selected yes!\n");
}

由于某些原因,scanf会捕获字符和换行符,因此它会对输入执行某些操作,然后还会打印“请仅输入'y'、'n'或'm'!”的提示信息。如果我在标准输入中输入多个字符,则它将为所有字符打印该行,并正确处理第一个字符。例如:
$ ./run
please enter [y]es, [n]o or [m]aybe: y<return>
you selected yes!
Please enter only 'y', 'n' or 'm'!
$ ./run
please enter [y]es, [n]o or [m]aybe: yes<return>
you selected yes!
Please enter only 'y', 'n' or 'm'!
Please enter only 'y', 'n' or 'm'!
Please enter only 'y', 'n' or 'm'!
$

如果我使用getchar,同样的事情会发生。我错过了什么?谢谢。
4个回答

13

你需要在 scanf("%c 之间加上空格才能正确运行:

scanf(" %c", &choice);

你还需要使用 &choice,而不是 choice!

编辑:在您处理此问题的同时,您可能还想查看 do while() 循环(除非教授特别要求使用 break)- 在验证用户输入时,do while 非常有效!


直到您收到意外的输入为止;尝试输入“y x z”作为示例。 - Clifford
哇,真是个传奇! - fergdev

6

fflush()在ISO C中并没有为输入流定义。它在微软的C运行时库中被定义,但不具有可移植性。

虽然“在%c之前加空格”的解决方案可能在用户输入预期数据时有效,但它会在许多情况下失败;例如尝试输入“y n y n”。控制台输入是基于行的;您最好确保丢弃整行,如下所示:

scanf( "%c", &choice ) ;
while( choice != '\n' && getchar() != '\n' ) /* do nothing*/ ;

4
更好的方法是使用fgetc()。scanf()应该始终是最后一招。

0
首先,我会简要概述。由于积分不足无法提交评论。 如果我们能看到输出的数量是(一个加上字符数) 这是因为当我们在输入字符后按回车键时,'\n'这个不可打印的字符也会被添加到您的字符串后面。
$ ./run
please enter [y]es, [n]o or [m]aybe: y<return>
you selected yes!
Please enter only 'y', 'n' or 'm'!  -----------> it is due to reading of the '\n' by scanf

编辑 由于我的积分不足,我无法将此作为评论发布。这是上面答案的解决方法。

那是一个解决问题的方法,不是吗?所以这只是对问题的评论(不是回答)。 - jogo
我的分数不够,我本来想发表意见的,但不知道会因此被踩。 - Kalu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接