Sign in to follow this  

Input Validation / Loop

This topic is 3716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Strange, I thought I posted this thread. ah well... Hi, so, I have a problem. I'm writing an application which validates the input to see if it's an integer or not. It works, but there are a few things I'm not sure about...

while(true)
	{
		cin.clear();

		while(!cin)
		{
			cin.clear();
			cin >> playerNumber;
		}
			cin.ignore(numeric_limits<int>::max(), '\n');	//Lets ignore string length up to the max int
															//or a carraige return (which ever comes first)
			
			if ( (! (cin >> value)))
			{
				cout << "Not an integer.\n";
			}
	
			else
			{
				  cout << "You entered: " << value << "\n";
				  playerNumber = value;

				  if(playerNumber < 10)
				  {
						cout << endl <<"Value must be greater than 10! "<< endl;
				  }
				  else
				  {
						break;
				  }
			}

	}

it appears to work, but the first time the loop enters the value has to be entered, then return pressed, then the value has to be entered again and return pressed again. This seems odd, have i done something wrong with the input stream? also it seems that the loop uses the call to cin.ignore() to stop it spamming messages at the user, I thought the call to cin() would have acted as a block?

Share this post


Link to post
Share on other sites
Let's break that down into pseudocode with some comments on what happens:


Until break:
Reset the error flags on cin.

While there is an error flag set on cin: # Note we just reset them, so this never happens!
Reset the error flags on cin.
Read into playerNumber.

Skip data from the input stream until we see a newline.
# This requires waiting until the user hits return, and then basically throws the result away.

Try to read into value. If an error flag is set:
Report an error.
Otherwise:
Report what was read.
Assign value to playerNumber.
If playerNumber < 10:
Report an error. # Oops, too late: we already assigned it!
Otherwise:
Break the outer loop.


The correct approach - i.e. the one that will actually work - is actually quite a bit simpler:


Try to read into value. While an error flag is set OR value < 10:
# Note that we only check 'value' when it was successfully read. This happens
# automatically due to short-circuit evaluation.
Report an error.
Reset the flags on cin. # This lets us attempt to read again on the next line.
Skip data from the input stream until we see a newline. # This prevents re-reading the bad input.
# Once we get here, we had an iteration where the read was successful and got
# a valid value.
Assign value to playerNumber.

Share this post


Link to post
Share on other sites
If you are like me, you might dislike ignore() and resetting failbits etc.

My method of choice is to read input into a string. I would then use std::stringstream (or boost::lexical_cast<>) to try convert the string to the correct type. If this fails, I discard the stringstream and try read another string.

Share this post


Link to post
Share on other sites

This topic is 3716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this