Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching strings while using cin for integer input [duplicate]

Tags:

c++

cin

I've seen similar posts to this all around google/stackoverflow. However, I can't find one close enough to my scenario and I don't know C/C++ well enough to port other suggestions over to my methods. Perhaps that's a sign in and of itself...

Regardless, here is my code:

while (true)
{
    print("\nSend message, enter command, or \"9\" for help.\n");

    if (cin >> input)
    {
        if (input == TERMINAL_HELP)
        {
            //Some help code.
        }
        else if (input == TERMINAL_EXIT)
        {
            //Some exit code.
        }
        else if (input < 4 && input >= 0)
        {
            // Some processing code.
        }
        else
        {
            print("Please enter a valid message.");
        }
    }
    else
    {
        print("Please enter a valid message.");
    }
}

The catches works fine for single characters or integers outside of the range [0-4]. But when I put a string in, it gets very weird. It keeps looping through itself infinitely. However after the first time this should be impossible because I do not press enter. It continues through as if it is receiving a blank infinitely.

If you have any suggestions or can point me in the direction of fixing my issue I'd appreciate it! Thanks!

NOTE:

I was trying to follow this, and it worked to some extent. (I got the cin >> input within the if statement idea from this link...) But it does not work to block strings from making the program loop oddly.

Good input validation loop using cin - C++

like image 571
eatonphil Avatar asked Sep 23 '26 21:09

eatonphil


1 Answers

Just to get you started with something..

Key points:

  • the iostreams (including cin) have something called "error flags"
  • when error occurs, the stream can be configured to either *) raise an exception *) skip next operations
  • the default configuration is .. to not throw and skip further operations

This means, that if you do:

cin >> integer1;
cin >> integer2; // *!
cin >> integer3; // !
cin >> integer4; // !

and if the user provides a non-integer at the line marked with (*), then at this point of time the cin will enter an error state and operations marked with (!) will be skipped.

Most probably this is why you get weird behavior like infinite read loops etc.

To handle this:

  • either configure the stream to throw exceptions - and catch them
  • or check error state after every few reads - and handle them

i.e.

cin >> integer1; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer2; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer3; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer4; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }

cin.reset clears error flags and allows further operation on the stream. However, all the trash-data will still linger in the stream. So, there's no point in trying to read further. After cin.reset you should somehow remove that bad-data and recover from the situation. I've marked the places with "..", because there are many ways to do it.

For example, cin.ignore..

Now please refer to all-that-other posts :) I'm sure that you will now quickly find a solution

EDIT: aargh.. sorry, I've floated too far from the actual answer.. What you actually wanted is not a good-errorhandling, but something similar to what sehe wrote: instead of reading an integers, you should read a "string" and then inspect it, and then either re-parse them as integers or treat as string-data..

like image 199
quetzalcoatl Avatar answered Sep 26 '26 11:09

quetzalcoatl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!