seelenkuchen
seelenkuchen

Reputation: 31

C++ if(!cin) causes loop

I tried to use if(!cin) to validate if the user input really is an integer. However my programm then just goes into an infinite loop never asking vor new input

do{
    cin >> temp->data;
    if(!cin){
        cout << "Please enter a Number!" << '\n';
        correct=false;
        }
   }while(correct==false);

Would be great if someone could help me :)

Upvotes: 3

Views: 3535

Answers (5)

Et Tol
Et Tol

Reputation: 1

For one, if you put a "!" before a condition in an if statement. That's supposed to be a "not" operator.

Upvotes: 0

M.M
M.M

Reputation: 141554

Your 'correct' variable actually doesn't do anything the way you are using it. It's not possible to exit the loop without correct being true; so you could do away with it, and just use a loop-exiting command when you have read the number.

Also, none of the answers posted so far handle the input being closed. They would go into an infinite loop in that scenario.

// A loop; we will break out when we successfully read a number.
while ( 1 )
{
// Prompt for a number and read it
    cout << "Please enter a Number!" << endl;
    cin >> temp->data;

// Exit loop if we successfully read
    if ( cin )
         break;

// Check to see if we failed due to the input being closed
    if ( cin.eof() )
    {
        cerr << "End of input reached.\n";
        return 0;   // depends what your function returns of course
    }

// reset the error condition that was caused by trying to read an integer and failing
    cin.clear();

// discard anything they previously typed
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

Moving on from this, a good design would be to actually have this code be an entire function in itself. Then you can call the function whenever you need to get a number safely, without needing to duplicate code. The function declaration might be:

void input_number(int &the_number, std::istream &in, std::string prompt);

which would output the_number, and it would handle end-of-file either by throwing an exception, or by relying on the caller to check for !cin, or even by returning a bool; whatever fits in best with your error handling overall.

Upvotes: 0

Veritas
Veritas

Reputation: 2210

When std::cin fails to read the input, the appropriate error flags are set. Therefore you want to reset the flags using std::cin.clear() so that the next input operation will work correctly and then skip everything until the new line using std::cin.ignore(..) in order to avoid similarly formatted input.

while (!(std::cin >> temp->data))
{
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "\nPlease enter a number!" << std::endl;
}

std::numeric_limits<std::streamsize>::max() returns the max amount of characters a stream can hold so that the whole line is guaranteed to be ignored.

Upvotes: 3

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

Use cin.fail() to check whether the user entered correct input. cin.fail() returns true if the last cin command failed, and false otherwise. Moreover, your loop is likely to be infinite, so you must also state an else where you will set the check flag correct to true. Thus, to invalidate the loop's condition and exit the loop in the case user entered correct input (see code below):

do{
    cin >> temp->data;
    if(cin.fail()){
        cin.clear();
        cin.ignore(10000, '\n');
        cout << "Please enter a Number!" << '\n';
        correct=false;
     } else {
        correct=true;
     }
}while(correct==false);

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

If you want to do that kind of check, read the data from cin to a string and convert the string to a number:

string str;
do{
    cin >> str;
    if(!cin){
        cout << "Please enter a Number!" << '\n';
        correct=false;
        }
    else{
        istringstream stream(str);
        stream >> temp->data;
        if(!stream){
            cout << "Please enter a Number!" << '\n';
            correct=false;
        }
     }

   }while(correct==false);

Upvotes: 0

Related Questions