Reputation: 295
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
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
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