Dusty Lew
Dusty Lew

Reputation: 81

Trying to use a while statement to validate user input C++

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!

Upvotes: 2

Views: 1182

Answers (4)

Niki Yoshiuchi
Niki Yoshiuchi

Reputation: 17551

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>

Upvotes: 3

Chubsdad
Chubsdad

Reputation: 25497

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){}

Upvotes: -1

Jerry Coffin
Jerry Coffin

Reputation: 490118

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.

Upvotes: 2

jkerian
jkerian

Reputation: 17016

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: Good input validation loop using cin - C++

Upvotes: 0

Related Questions