我试图在C中写一个简单的菜单。
这是我建议的代码:
while (end == 0) {
printf("Main menu\n");
printf("=========\n");
printf("1) Option 1.\n");
printf("2) Option 2.\n");
printf("3) Option 3.\n");
printf("4) Option 4.\n");
printf("0) Exit");
printf("\n");
printf("Choose an option: ");
fgets(&menu_option,1,stdin);
switch (menu_option) {
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
}
}
但是,执行此代码时,循环永远不会结束。
出了什么问题?
谢谢。
编辑:当我说'#34;循环永远不会结束"时,我想说我不能写任何选项,因为菜单一次又一次出现。
答案 0 :(得分:3)
来自fgets
fgets()函数必须从流中读取字节到s指向的数组,直到读取n-1个字节,或者读取a并将其传送到s,或者遇到文件结束条件。然后该字符串以空字节终止。
由于您提供1
的长度,n-1
将为0
,因此您的输入永远不会存储在menu_option
中。将其更改为char数组
char menu_option[10];
// ...
fgets(menu_option, sizeof(menu_option), stdin);
switch (menu_option[0]) {
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
}
更新
必须使用char数组,因为您需要足够的空间来存储输入。缓冲区的最小大小是两个字符,例如char buf[2]
,因为fgets
存储了您的输入以及终止NUL
字符。
循环迭代两次甚至更多次,因为当您输入例如 1返回或 1 3 2返回,它将首先返回1
,然后返回3
,2
,最后返回返回。如果你想读取整行并只使用第一个数字,你的缓冲区必须大于2,例如10甚至256。
答案 1 :(得分:1)
fgets
读取字符串而不是字符。声明
fgets(&menu_option,1,stdin);
将字符串存储到menu_option
但是要存储字符串,您需要的字符大小至少为2
个字节。
char menu_option[2];
...
fgets(menu_option,2,stdin);
int c;
while((c = getchar()) != '\n' && c != EOF); // This will be needed to flush your input buffer
switch (menu_option[0]) {
...
...
}
答案 2 :(得分:1)
来自:http://www.cplusplus.com/reference/cstdio/fgets/
fgets
char * fgets ( char * str, int num, FILE * stream );
从流中获取字符串。
从流中读取字符并将其存储为C 字符串转换为str,直到读取(num-1)个字符或者a 到达新行或文件结尾,以先发生者为准。
换行符使fgets停止读取,但它被认为是a 函数的有效字符并包含在复制到的字符串中 海峡
终止空字符会自动附加到 字符复制到str。
由于您为数字指定了1,因此读取了0个字节,并且唯一发生的是附加了终止空字符。结果是一个无限循环,其中没有任何东西被读取。
答案 3 :(得分:1)
由于您在评论中表示不喜欢使用字符串,因此这里的替代实现只需对问题代码进行最少的更改:
while (end == 0) {
printf("...menu print snipped...\n");
int ch = getchar();
switch (ch) {
case EOF: // end of file or error, fall through to exit option
case '0': end = 1; break;
case '1': option1(); break;
case '2': option2(); break;
case '3': option3(); break;
case '4': option4();
// default: // add error message?
}
// ignore any extra chars in the same line
while ((ch = getchar() != '\n') {
// test for end of file and set end to true
if (ch == EOF) {
end = 1;
break;
}
}
}
注意额外的循环,它将读取并丢弃输入行的其余部分。没有它,用户可以在一行上输入几个选项,这可能是不可取的。另请注意,如果选项函数读取更多用户输入,请考虑如何处理长行。例如,将额外循环移动到切换之前(并添加另一个变量以读取丢弃的字符)。实际上你应该把额外的循环放在它自己的函数discard_until_newline
上。