Ozz*_*zah 5 c++ stdin menu infinite-loop
假设我们有一个菜单向用户显示一些选项:
Welcome:
1) Do something
2) Do something else
3) Do something cool
4) Quit
Run Code Online (Sandbox Code Playgroud)
用户可以按1 - 4然后按回车键.程序执行此操作,然后将菜单返回给用户.无效选项应该只显示菜单.
我有以下main()方法:
int main()
{
while (true)
switch (menu())
{
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
case 3:
doSomethingCool();
break;
case 4:
return 0;
default:
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是menu():
int menu()
{
cout << "Welcome:" << endl
<< "1: Do something" << endl
<< "2: Do something else" << endl
<< "3: Do something cool" << endl
<< "4: Quit" << endl;
int result = 0;
scanf("%d", &result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
输入数字类型效果很好.输入1 - 4会使程序执行所需的操作,然后再次显示菜单.输入此范围之外的数字(例如-1或12)将再次按预期显示菜单.
但是,输入类似"q"的内容只会导致菜单无限地反复显示,甚至无法停止获取用户输入.
我不明白这是怎么发生的.很明显,menu()正在调用菜单,因为菜单会一遍又一遍地显示,但却scanf()是其中的一部分menu(),所以我不明白程序如何进入这种错误状态,用户不会被提示输入.
我最初做过的cin >> result是完全相同的事情.
编辑:似乎有一个相关的问题,但原始源代码已从pastebin中消失,其中一个答案链接到一篇文章,显然曾经解释过为什么会这样,但现在是一个死链接.也许有人可以回复为什么会发生这种情况而不是链接?:)
编辑:使用这个例子,这是我解决问题的方法:
int getNumericalInput()
{
string input = "";
int result;
while (true)
{
getline(cin, input);
stringstream sStr(input);
if (sStr >> result)
return result;
cout << "Invalid Input. Try again: ";
}
}
Run Code Online (Sandbox Code Playgroud)
而我只是更换了
int result = 0;
scanf("%d", &result);
Run Code Online (Sandbox Code Playgroud)
同
int result = getNumericalInput();
Run Code Online (Sandbox Code Playgroud)
当您尝试将非数字输入转换为数字时,它会失败并且(重要部分)将该数据保留在输入缓冲区中,因此下次您尝试读取int时,它仍然在等待,并再次失败 - - 再一次,永远.
有两种基本方法可以避免这种情况.我更喜欢的是读取一串数据,然后从中转换为数字并采取适当的操作.通常,您将使用std::getline读取所有数据直到换行,然后尝试转换它.因为它会读取正在等待的任何数据,所以你永远不会在输入中"卡住"垃圾.
替代方案(特别是如果转换失败)用于std::ignore从输入读取数据(通常)到下一个换行符.