用户输入数字+字符时出错

时间:2014-05-10 16:42:04

标签: c++

这是我的代码,当用户的输入不是数字时显示错误。但是,当用户输入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');

1 个答案:

答案 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
}