这是我的代码,当用户的输入不是数字时显示错误。但是,当用户输入alphanumberic(例如:123abc)时,它会重复两次错误消息。
#include <iostream>
using namespace std;
int main()
{
int option;
do
{
cout <<"Type random characters ( E.g : asdwefef ) " ;
cin >> option;
if (cin.good()) // If numeric
{
}
else
{
cout << "Invalid input!" << endl;
cin.clear(); // Clear buffer
cin.ignore( INT_MAX, '\n' );
}
}while (option != 0);
return 0;
}
我该如何解决?我尝试过使用以下内容,但结果是一样的。
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
答案 0 :(得分:2)
输入流逐个解析字符。对于数字提取,流将不断读取字符,直到找到非数字字符。如果它已经成功地将字符写入其操作数,并且没有尝试读取非数字字符,则不会设置std::ios_base::failbit
。因此,std::cin.good()
将在第一次迭代时返回true
。
通常,检查good()
不是评估流有效性的首选方法。 Streams有一个内部布尔运算符,可以为您执行此操作。您所要做的就是将实际输入操作包含在布尔表达式中:
if (std::cin >> option) {
// successful input
}
else {
// unsuccessful
}
现在,要检查整个输入是否为数字,最好是读入字符串并手动进行解析,因为流不能自行执行此操作(默认情况下)。或者,要使流本身执行此操作,您可以创建自定义std::num_get<char>
构面,如果可以确定输入不是完全数字,则设置错误掩码。这个方面将被安装到流的区域;您可以随时通过更改为原始文件来卸载它:
class num_get : public std::num_get<char>
{
public:
iter_type do_get( iter_type it, iter_type end, std::ios_base& str,
std::ios_base::iostate& err, long& v) const
{
auto& ctype = std::use_facet<std::ctype<char>>(str.getloc());
it = std::num_get<char>::do_get(it, end, str, err, v);
if (it != end && !(err & std::ios_base::failbit)
&& ctype.is(ctype.alpha, *it))
err |= std::ios_base::failbit;
return it;
}
};
将其安装到语言环境中并将imbue()
语言环境安装到流中以获得所需的行为:
std::locale original_locale(std::cin.getloc());
std::cin.imbue(std::locale(original_locale, new num_get));
if (std::cin >> option) {
// input was entirely numeric
}
else {
// input was not entirely numeric
}