Ernesto
Ernesto

Reputation: 295

do...while loop not displaying what I want

So basically I have been working on this one loop for about 7 hours today. It is not behaving how I believe it should. When I enter a fail state with the cin (row is a char, column is an int, so if for instance I enter aa1 instead of a1) it will cout invalidCoord twice before asking for a new coord.

do
{
    confirmShot = false;
    validShot = false;
    failShot = false;
    cout << enterCoord;
    cin >> row >> column;
    if (cin.fail())
    {
        cin.clear();
        cout << invalidCoord << endl;
        failShot = false;
        continue;
    }
    if (failShot == true)
    {
        row = toupper(row);
        xCoord = column - 1;
        yCoord = static_cast<int>(row - 'A');
        if(xCoord > 9 || xCoord < 0 || yCoord > 9 || yCoord < 0)
        {
            cout << invalidCoord << endl;
            validShot = false;
        }
        else
        {
            validShot = true;
        }
    }
    else
    {
        continue;
    }
    currentTile = tileToSymbol(computerBoard[xCoord][yCoord]);
    if (validShot == true)
    {
        switch(currentTile)
        {
            case '~':
            case 'a':
            case 'b':
            case 's':
            case 'd':
            case 'p':
                cout << "You have already shot at " << row << column << "." << '\n'
                    << "Please pick a new coordinate!" << endl;
                validShot = false;
                confirmShot = false;
                break;
            default:
                confirmShot = true;
        }
    }
    else
    {
        continue;
    }
}
while(!confirmShot);

Output:

Your shot:  Enter the coordinates for a shot (e.g. B2) cc2
Invalid coordinates!
Pick a row value between A and J
and a column value between 1 and 10.
Enter the coordinates for a shot (e.g. B2) Enter the coordinates for a shot (e.g. B2) cc2
Invalid coordinates!
Pick a row value between A and J
and a column value between 1 and 10.
Enter the coordinates for a shot (e.g. B2) Enter the coordinates for a shot (e.g. B2) c2
Enter the coordinates for a shot (e.g. B2) c2

Additionally, I cannot figure out how to get the do...while loop to exit anymore. It used to exit fine before I realized that I had to handle the failstate if someone entered a non-integer as the second character.

I added the "continue" code because someone I was talking to said I needed it to skip to the next section, and if I remove it, the program locks up, although before I tried to handle the failstate I did not have the continue code in there, and it worked just fine.

I really just need to get this loop working correctly, but I've exhausted my ability. How can I handle the failstate, keep invalidCoord from display twice (I honestly have no idea why it is doing that), exit the loop after receiving valid entry, and save the day?

Upvotes: 0

Views: 101

Answers (2)

organicoman
organicoman

Reputation: 154

ok, your problem is the understanding of the std::cin object.

this is how it works

std::cin starts at position pos_type p = -1 then increment this position as it fetches chars from the keyboard buffer, when it encounter an error in parsing the entered chars, it sets the position to eof, so when next time it runs, it will return eof then do nothing.

to illustrate this in your code, insert this snippet under: cin<<row<<column;

cin << row << column ;
cout << "p =" << cin.tellg();

it will output the following (only interesting part is printed here)

// when you enter for expel: c1 - which is correct input, it prints
p = 2; // advanced two position in the buffer until EOF
// when you enter wrong input: cc1 - it prints
p =-1;
// next run just after the error message, it will print
p = 3;//this number is the number of character read last time and it coincide with EOF
// right after, it will prompt you for another input

which means std::cin needs to consume all the character in the buffer then sets the position indicator to -1, then start extracting character again.

and that's exactly why you have a duplicated message. So how to fix it?

this is an ugly hack:

//inside the loop under
cin.clear()
cin.seekg(0); // rewind...uuurrrgg, ugly!! but it works

what I suggest is to restructure your code. Use Boolean logic to design a beautiful code flow chart. Error like this in a code base, means that the code is more a spaghetti code rather than a well written code.

Do your best, Good luck!

Upvotes: 0

Jesse
Jesse

Reputation: 293

I may be over simplifying it, and please comment if I am wrong but I think the error is simply in your if statements.

It appears as though if (failShot == true) never gets called since failShot was initialised as false, and only gets updated as false again whenever you check if (cin.fail()). If I am understanding this correctly, you want if (failShot == true) to get called if your cin does not fail. In this case, initialising failShot as True would fix your error.

Try changing:

    failShot = false;

To:

    failShot = true;

Upvotes: 1

Related Questions