zzari
zzari

Reputation: 323

Infinite while loop happens when asking user for 2 numbers

I'm trying to implement a simple game where user is asked for 2 valid integer coordinates between 0 and 10. (int row, int column)

An exemple of what I would realize is:

Insert coordinates: 4C
*Error, number of row and column must be integer

Insert coordinates: 44 2
*Error, number of row or column are too high

Insert coordinates: 4 3
The coordinates you entered are (4,3)

I realized all of these with a do-while cycle.

int r,c;
do{
cout<<"Insert coordinates: ";
cin>>r>>c;
    if (cin.fail())
{
    cout << "ERROR: Number of row and column must be integer." << endl << endl;

}
    if ((r<0 || r>10) || (c<0 || c>10)
{
    cout << "*Error, number of row or column are too high [0-10]" << endl << endl;

}
 cout<<endl;
}
while (((r<0 || r>10)||(c<0 || c>10)) || cin.fail());

This code doesn't work properly. If I enter 2 numbers between 0 and 10, it works. If I enter a number bigger then 10, it also works. But if I entered a character the program goes into an infinite loop, and does not work properly.

How to implement this to handle errors with character input? Is there a way to recognize, and remain inside the while cycle, if user inputs a character?

Upvotes: 0

Views: 270

Answers (4)

Zac Howland
Zac Howland

Reputation: 15870

The program goes into an infinite loop because you never clear the fail state. You can simplify your entire loop:

#include <iostream>
using namespace std;

int main() 
{
    int r = -1;
    int c = -1;
    bool valid = false;
    do
    {
        cout<<"Insert coordinates: ";
        if (cin >> r >> c)
        {
            if (r >= 0 && r <= 10 && c >= 0 && c <= 10)
            {
                valid = true;
            }
        }
        else
        {
            cin.clear();
            cin.ignore();
        }

        if (!valid)
        {
            cout << "ERROR:  Number of row and column must be an integer between 0 and 10." << endl;
        }
    } while (!valid);

    cout << "You entered (" << r << ", " << c << ")" << endl; 

    return 0;
}

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409442

If you enter a letter instead of a number, then that letter is not extracted from the input buffer, so your code will continue to fail forever.

If the input fails (why not use e.g. if (!(cin >> r >> c))?) then you can skip the line by doing calling the ignore function:

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

You also want to clear the failbit as it's not cleared automatically, this is done with the clear function.


You can also bypass this problem by getting the whole line, and using std::istringstream for the parsing:

do
{
    std::string line;
    if (!std::getline(std::cin, line))
        ... // Could not read from input

    std::istringstream iss(line);
    int r, c;
    if (!(iss >> r >> c))
        ... // Failed to parse as numbers

    ...

} while (...);

Upvotes: 1

Santosh Sahu
Santosh Sahu

Reputation: 2244

(((r<0 || r>10)||(c<0 || c>10)) || cin.fail());

change to

 (((r>0) && (r<10))||((c>0) && (c<10)))     //It will work, no need to check cin.fail();

If cin fails then it might produce errors in buffer so better to quit the program..

Upvotes: 0

Eutherpy
Eutherpy

Reputation: 4581

You could simply check if characters were entered, for example:

if (x >= 0x41 && x <= 0x7A)
cout<<"error, you entered a letter";

Upvotes: 0

Related Questions