在此代码中
void menu() {
char name[MAXNAME];
float a;
char c;
cout << "n\tnew transaction\n";
cout << "v\tview all transactions\n\n";
c = getchar();
flushbuf();
switch (c) {
case 'N':
case 'n':{
cout << "What is the name? (press 'b' to go back to the menu)\n";
fgets(name, sizeof name, stdin);
replaceTrailingNl(name); // replaces trailing '\n' (from fgets) with '\0'
if (strcasecmp(name, "b") == 0)
menu();
do {
flushbuf();
cout << "What is the amount?\n";
} while (scanf("%f", &a) == 0);
if (writeTransData(name, a))
cout << "Successfully saved!\n";
else
cerr << "writeTransData: Error occurred\n";
break;}
}
}
void flushbuf()
{
int temp;
while ((temp = getchar()) != EOF && temp != '\n') ;
}
当输入'b'作为“名称是什么”提示的答案时,调用menu()(显示菜单),显示菜单然后按'n'创建一个新的交易。一切都按预期进行,直到break
。 break
完成后,我得到“数量是多少?\ n”再次询问,我实际上可以输入内容。这是怎么回事?我做错了什么?
答案 0 :(得分:2)
再次拨打menu()
并不会结束当前对menu()
的呼叫。呼叫#2将完成,控制流将返回呼叫#1并进入do
循环。
最简单的解决方法是:
if (strcasecmp(name, "b") == 0) {
menu();
return;
}
但是,这是一个糟糕的设计,因为您正在使用递归和无用的堆栈。您可以使用goto
:
void menu() {
char name[MAXNAME];
float a;
char c;
menu_prompt:
cout << "n\tnew transaction\n";
cout << "v\tview all transactions\n\n";
c = getchar();
flushbuf();
switch (c) {
case 'N':
case 'n':{
cout << "What is the name? (press 'b' to go back to the menu)\n";
fgets(name, sizeof name, stdin);
replaceTrailingNl(name);
if (strcasecmp(name, "b") == 0)
goto menu_prompt;
但是,通常,您将使用外部循环进行输入。然后,您将使用continue
和break
,具体取决于您是否希望用户再次尝试。