每当我输入无法转换为整数的内容时,我就会得到一个无限循环。有什么建议吗?
cout << "Selection: ";
cin >> choice;
while((choice < 0)||(choice > 6)||(cin.fail())) {
cout << "That isn't a number." << endl;
cin.clear();
cout << "Selection: ";
cin >> choice;
}
答案 0 :(得分:6)
仅仅clear
还不够:cin
会一次又一次地读取该字符。
您需要ignore
。
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
是实现这一目标的常用方法。
另一种方法是将整行读作字符串,然后解析它(如C#/ Java ecc。)。在代码方面,它可能是:
string s;
getline(cin, s);
int n = std::stoi(s);
请注意,std::stoi
可以投放std::invalid_argument
或std::out_of_range
。使用这种方法,您不必忽略任何事情(因此更容易处理/学习),尽管您可能需要捕获可能的异常。
考虑到这一点,即使被其他语言使用,此方法在逻辑上也不正确:例外情况应该仅针对特殊情况(例如内部I / O故障)抛出 。错误的用户输入是您所期望的,而不是。
答案 1 :(得分:1)
isocpp.org faq中介绍了这一点。它建议使用while (std::cin >> i)
形式的循环,以便在提取失败时循环终止。提取将继续失败,因为std::cin
不从输入流中提取无效字符。要丢弃这些,您需要使用std::cin.ignore
。通常,您可以将任意大的数字作为第一个参数,但使用std::numeric_limits<std::streamsize>::max()
( #include <limits>
)代替它是惯用的。
循环可以简洁地写成:
while(!(std::cin >> choice) || (choice < 0) || (choice > 6)) {
cout << "Invalid choice." << endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
或者,您可以将提示放在循环条件中:
while((std::cout << "Selection: ")
&& (!(std::cin >> choice) || (choice < 0) || (choice > 6))) {
cout << "Invalid choice." << endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
不需要“无效字符”诊断,因为!(std::cin >> choice)
涵盖了该字符。示例运行:
Selection: a
Invalid choice.
Selection: b
Invalid choice.
Selection: c
Invalid choice.
Selection: d
Invalid choice.
Selection: 15
Invalid choice.
Selection: 10
Invalid choice.
Selection: 5