views:

131

answers:

4

I am new to C++ and am in a class. I am trying to finish the first project and so far I have everything working correctly, however, I need the user to input a number to select their level, and would like to validate that it is a number, and that the number isn't too large.

while(levelChoose > 10 || isalpha(levelChoose))
{
    cout << "That is not a valid level" << endl;
    cout << "Choose another level:";
    cin >> levelChoose;
}

That is the loop I made, and it sometimes works. If I type in 11 it prints the error, and lets me choose another level. However if the number is large, or is any alpha character it floods the screen with the couts, and the loop won't end, and I have to force exit. Why does it sometimes stop at the cin and wait for user input, and sometimes not? Thanks for the help!

A: 

levelChoose appears to be an integer type of some form (int, long, whatever).

It's not valid to input a character into an integer directly like that. The input fails, but leaves the character in the incoming buffer, so it's still there when the loop comes around again.

Here's a related question: http://stackoverflow.com/questions/2075898/good-input-validation-loop-using-cin-c

jkerian
+2  A: 

From your description, it seems likely (nearly certain) that levelChose is some sort of numeric type, probably an integer.

When you use operator>> to read a number, anything that couldn't be part of a number (e.g., most letters) will be left in the input buffer. What's happening is that you're trying to read the number, it's failing and leaving the non-digit in the buffer, printing out an error message, then trying to read exactly the same non-digit from the buffer again.

Generally, when an input like this fails, you want to do something like ignoring everything in the input buffer up to the next new-line.

Jerry Coffin
A: 

I suspect the part while(levelChoose > 10..... This does not restrict level to less than 10 (assuming greater than 10 is a large number in your context). Instead it probably should be while(levelChoose < 10...

To check that an expression is not too large, the following could be a possibility to validate (brain compiled code!!)

const unsigned int MAX = 1000;

unsigned int x;
cin >> x;

while(x < MAX){}
Chubsdad
The logic was correct. He just didn't realise that `cin` needs to be flushed between iterations, otherwise there might be junk values in the buffer.
Chinmay Kanchi
+2  A: 

This is an annoying problem with cin (and istreams in general). cin is type safe so if you give it the wrong type it will fail. As you said a really large number or non-number input it gets stuck in an infinite loop. This is because those are incompatible with whatever type levelChoose may be. cin fails but the buffer is still filled with what you typed so cin keeps trying to read it. You end up in an infinite loop.

To fix this, you need to clear the fail bit and ignore all the characters in the buffer. The code below should do this (although I haven't tested it):

while(levelChoose > 10 || isalpha(levelChoose))
{
    cout << "That is not a valid level" << endl;
    cout << "Choose another level:";
    if(!(cin >> levelChoose))
    {
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

Edit: numeric_limits<> is located in the limits include:

#include<limits>
Niki Yoshiuchi
The compiler says numeric_limits has not been defined, although I have included iostream, and am using namespace std.
Dusty Lew
Sorry! I should have mentioned that you'll need to #include<limits>
Niki Yoshiuchi
ok cool! That is exactly what I need, I think :D
Dusty Lew
I ended up doing thiswhile(levelChoose > numLevels || isalpha(levelChoose)) { cout << "That is not a valid level" << endl; cout << "Choose another level:"; cin.clear(); cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); cin >> levelChoose; } using what you said, it worked perfectly! I had to get rid of the if(!cin) part, because sometimes it would require 2 numbers before the error actually printed out. But that is perfect! Thank you so much
Dusty Lew
As a side note, this works for removing alpha, but if the number is too large, it just exits the loop and proceeds to the next statement.
Dusty Lew