我是这个编程世界的新手。我在学校学习编程。我的老师最近要求班级创建一个选项有限的菜单,该菜单将以哨兵价值结束。 所以这是我的编码:
#include <stdio.h>
void menu(void);
void choice1();
void choice2();
void choice3();
char choice;
int main() {
do {
menu();
if (choice =='1')
choice1();
else if (choice =='2')
choice2();
else if (choice =='3')
choice3();
else if (choice =='4')
break;
else
printf("Invalid character.");
} while (choice != '4');
return 0;
}
void menu(void) {
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
scanf("%c", &choice);
}
void choice1() {
printf("\nChoice 1\n");
}
void choice2() {
printf("\nChoice 2\n");
}
void choice3() {
printf("\nChoice 3\n");
}
当我尝试运行它时,通过输入数字1
,2
,3
,输出结果出来,但之后是函数menu()
以及行&#34;字符无效。&#34;出来。至于另一个角色,menu()
和&#34;无效的角色&#34;出来两次。号码4
确实结束了该计划。我是否有任何改进可以确保menu()
和行&#34;无效字符。&#34;没有不必要的出现?
答案 0 :(得分:4)
在行缓冲输入中,读取单个字符后,换行符会在缓冲区中徘徊,以便选择&#39;因此你会无意中得到Invalid character.
。
阅读完选择
后,您需要清除缓冲区scanf("%c", &choice);
while(getchar()!='\n')
/* Wasting the buffer
* Hence ensuring that the character you enter
* is indeed considered for 'choice'
*/
;; // Do nothing in particular
作为旁注,您的程序看起来像是switch-case命令的典型用例,也许您的老师希望您使用它。
考虑@chqrlie评论中[ this ]提到的情况,解决方法是在
之后添加scanf("%c", &choice);
以下行
int c;
while ((c = getchar()) != EOF && c != '\n')
;; //Wasting the buffer
答案 1 :(得分:2)
正如其他答案中已经提到的,问题是换行符。
当您按1
然后按Enter键时,您将获得两个字符,即1
和\n
。因此,在处理Invalid character
时,您的循环会运行两次并打印\n
。
以下是您的问题的替代解决方案。只需在%c
之前添加一个空格。
scanf(" %c", &choice);
这是有效的,因为该空格将匹配任意数量的空白字符,从而与\n
匹配并将其删除。
从手册页:
一系列空白字符(空格,制表符,换行符, 等等.......)。该指令匹配任意数量的 输入中的空格,包括无空格。
其他评论
您应该始终检查scanf
返回的值,以确保您读取正确数量的值。
if (scanf(" %c", &choice) != 1)
{
// Add error handling ....
// For instance you could terminate the program like
exit(1);
}
在你的程序中choice
是一个全局变量。通常,如果可能,应避免使用全局变量。在您的情况下,您可以在choice
中将main
作为局部变量,并让menu
返回char
。像:
// char choice; Remove global variable
int main() {
char choice; // Add local variable
do {
choice = menu(); // Assign to local variable
.....
}
char menu(void) { // Make the function return a char
char choice; // Add local variable
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf("%c", &choice) != 1) exit(1); // Assign to local variable
// On failure -> exit
return choice; // Return value of local variable
}
答案 2 :(得分:2)
问题很简单:终端是行缓冲的:您必须按Enter键才能使输入可用于您的程序,第一个scanf("%c", &choice)
检索输入的字符,第二个调用检索换行符({{1由enter键生成的。
有多种方法可以避免此问题。您可以在'\n'
格式之前添加空格 scanf
:%c
,或者您可以在第一个字符后读取字符,直到获得scanf(" %c", &choice);
请注意,必须检查'\n'
的返回值,以避免在用户输入文件结尾时出现未定义的行为。建议避免使用全局变量:函数scanf
应该返回指定的选项。使用menu()
语句也更为惯用。
以下是更正后的版本:
switch
答案 3 :(得分:1)
当我尝试运行它时,通过输入数字1,2,3,输出来了 然后在功能菜单()和行&#34;无效之后 。字符#&34;出来了。
由于您在每个号码后按下了新的换行符,因此发生了这种情况。它本身就是一个字符,循环再循环一次。因为它是一个无效的角色,这就是为什么&#34;无效的角色。&#34;正在展示。
在scanf()之后尝试使用getchar()
。
答案 4 :(得分:1)
您可以写scanf(" %c",&choice);
(使用空格)而不是scanf("%c",&choice);
答案 5 :(得分:0)
编辑:修复了我之前的while循环,可能会无法退出:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (1) {
char c = scanf("%d",&choice);
if (c == EOF || choice == 4) break;
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}
如果需要,可以使用功能,但在这种情况下不需要。您需要了解循环实际运行的次数,并将其与您期望的进行比较。
我之前的代码:
#include <stdio.h>
int main() {
int choice;
printf("Menu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("2) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
while (scanf("%d", &choice) && choice != 4) {
if (choice == 1 || choice == 2 || choice == 3) {
printf("Choice %d.\n", choice);
} else {
printf("Invalid character.\n");
}
}
return 0;
}