0

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?

StarPilot
  • 2,246
  • 1
  • 16
  • 18
zzari
  • 283
  • 1
  • 5
  • 13

4 Answers4

1

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 (...);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Pulling it out of an input stream and putting it into another input stream to read in is a bit overkill. – Zac Howland Nov 13 '13 at 15:45
  • @ZacHowland Not always, it can simplify things, especially since you no longer have the problem that the `std::cin` stream will get the `failbit` set on erroneous input, or that some characters will linger in the input buffer. – Some programmer dude Nov 13 '13 at 15:50
0
(((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..

Santosh Sahu
  • 2,134
  • 6
  • 27
  • 51
0

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

if (x >= 0x41 && x <= 0x7A)
cout<<"error, you entered a letter";
Eutherpy
  • 4,471
  • 7
  • 40
  • 64
0

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;
}
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • Also with your code, the do-while goes into an infinite loop if I entered for example " a 4". :/ – zzari Nov 13 '13 at 15:42
  • It does not. It will loop around again asking you for the input again (because your first input failed), clear the state, and let you retry *until* you enter valid input. – Zac Howland Nov 13 '13 at 15:44
  • try to compile it and run! If i entered a number bigger than 10 it end cycle, while i would ask user another input. If i entered a char goes in loop. – zzari Nov 13 '13 at 16:02
  • What you just said makes no sense. This only breaks out of the loop when you enter valid numbers between 0 and 10, inclusive. – Zac Howland Nov 13 '13 at 16:54
  • I think I did forget to transpose the `cin.ignore` call though. Fixed in the compiled example. – Zac Howland Nov 13 '13 at 17:05