cin type check failed for '+'/'-'

cin type check failed for '+'/'-'

The scenario is: input integers and characters alternatively and read them into variables of the right type. I took the straightforward approach: read anyways as if they were all integers; when failed, reset cin flags and read as characters.

int a;
char c;
while (true) {
    cin >> a;
    if (cin.fail()) {
        if (cin.eof()) {
            cout << "eof" << endl;
            break;
        }
        cin.clear();
        cin >> c;
        cout << "fail: " << c << ": " << int(c) << endl;
    }
    else {
        cout << "success: " << a << endl;
    }
}

It works just fine except for the very two characters: +, -. For instance, when you input 2 4 + 5 *, the output would be:

success: 2
success: 4
fail: 5: 53
fail: *: 42
eof

For *, it works; but for +, it seems that + is lost and 5 is read instead. I did some tests myself (e.g. using cin.get() instead) and found that: after cin >> a failed when encoutering +, + is consumed and the stream position points at the space between + and 5.

What makes + and - special? After some researches, I think the reason is possibly that: when cin expects an integer, the + or - it encounters is accepted as a possible prefix of integers like +5, -3, etc. This leads to the fact that + is consumed, rather than remains in the input stream like other characters.

How do you interpret the problem? How to fix the code to make it function properly?

PS: I know that one alternative solution is to read them all as strings and then do further parsing. I'm just curious whether it's possible to modify it based on the original approach. This way I could be more clear about the machanisms behind cin.

Answer

The comments to your question show that there are much more to think than the mere "+/-" issue.

Yet as to tackle this issue, your analysis is correct in the sense that these characters can be interpreted as the beginning of an int and got consumed.

A workaround for this issue only is to parse char by char and not by int and to handle specifically + and -:

int a;
char c;
while (true) {
    char ch;
    if (std::cin >> ch) {
        if (ch == '+' || ch == '-') {
            // Consume the special character and continue
            std::cout << "special char: " << ch << '\n';
            continue;
        } else {
            // Try to read the character as an integer
            std::cin.putback(ch);
            if (std::cin >> a) {
                std::cout << "success: " << a << '\n';
            } else {
                std::cin.clear();
                std::cin >> c;
                std::cout << "fail: " << c << ": " << int(c) << '\n';
            }
        }
    } else if (std::cin.eof()) {
        std::cout << "eof" << '\n';
        break;
    } else {
        std::cin.clear();
        std::cin >> c;
        std::cout << "fail: " << c << ": " << int(c) << '\n';
    }
}

Take notice of the usage of putback that allows to "unconsume" +or - and then try to read an int.

input:

24+5

output

success: 24
special char: +
success: 5

But remember: it's only a quick workaround for this single issue but parsing a possibly ill -formed expression will raise many other issue that won't be solved by merely elaborating upon this fix.

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles