Errors not printing correctly..Is this logic flow correct? c++ - c++

Example user input:
PA1 9 //correct
PJ1 9 //wrong, error printed "Invalid row" because it is not between A and I
PA11 9 //wrong, error printer "Invalid column" because it is not between 1 and 9.
The problem I am having is that it should clear the remaining input and then ask for the user to enter the "move" again, and it is not.
Where did I go wrong? I've been at it for a while and still got no progress..
void clearInput()
{
cin.clear();
}
bool getCoords(int & x, int & y)
{
char row;
while(true){
cin>>row>>y;
row=toupper(row);
if(/*(id=='P' || id=='p' || id=='D' || id=='d') && */row>='A' && row<='I' && isalpha(row) && y>=1 && y<=9){
x=row-'A';
y=y-1;
return true;
}
else if(!(y>=1 && y<=9)){
cout<<"Invalid column\n"<< endl << endl;
cout<<y;
clearInput();
cout<<y;
//return false;
}
else{
cout<<"Invalid row\n"<< endl << endl;
clearInput();
//cout<<x<<y;
//return false;
}
}
}

cin's clear member function doesn't clear the remaining input, it resets the error flags on the stream (which could get set e.g. because you tried to read an integer but there were non-digit characters in the input). I guess you really want to discard the input up to the next newline; one way to do this would be to call cin.ignore with '\n' as the delimiter.
Another thing that could be an issue (but might just be code left out in the question ;)) is that the while(true) loop that you've written to repeatedly ask for input until there's no error doesn't contain the board-redrawing logic you talk about in your comment. So you won't see this until the getCoords function finds error-free input and returns.

Related

How to ignore wrong cin input in C++?

This is code for a 4x4 tic-tac-toe game. I am new to programming. I don't know how to ignore wrong input from the user. I tried searching Google, I found cin.clear() and cin.ignore(). They did work a little bit, but not fully working. For example, if the user enters 11111111 4 o as input, the program exits instead of ignoring this. How to ignore this input?
And what are cin.clear() and cin.ignore() doing?
char game[4][4];
int r, c;
char ans;
cin >> r >> c >> ans;
--r, --c;
if (!check_ok(r, c, ans)){
cout << "try again: select available ones only!!!\n";
--count;//count checks for 16 turns through while loop
}else{
game[r][c] = ans;
++count1;
}
bool Game::check_ok(int a, int b, char an) {
if (game[a][b] == ' ' && a < 4 && b < 4 && ((count1 % 2 == 0 && an == 'x') || (count1 % 2 != 0 && an == 'o'))){
game[a][b] = an;
return true;
}
else{
cin.clear();
cin.ignore();
return false;
}
}
OK. User input is hard.
Interactive user input is line based.
User inputs some values and then hits return. This flushes the stream and unblocks the readers to get the value from the stream. So you should design your input code to be line based.
The first question seems to be is all the input on one line or do they input the values with a return between each? You can determine this with some outut to the user then follow the rules defined by your instructions.
So lets do a line based input example:
do {
// Your instructions can be better.
std::cout << "Input: Row Col Answer <enter>\n";
// Read the user input. 1 Line of text.
std::string line;
std::getline(std::cin, line);
// convert user input into a seprate stream
// See if we can correctly parse it.
std::stringstream linestream(std::move(line));
// Notice we check if the read worked.
// and that the check_ok() returns true.
// No point in call check_ok() if the read failed.
if (linestream >> r >> c >> ans && check_ok(r, c, ans)) {
break;
}
std::cout << "Invalid Input. Please try again\n";
}
while(true);
i think instead of ignoring the wrong input you should limit the users input into the ideal inputs only. maybe an if statement could help
if(input != ideal_input)
{
cout>>"invalid input";
}
else
{
//progress in the game
}

Setting up a loop waiting for user input (C++)

I'm trying to get a simple tic-tac-toe program to function in the console as a way to make sure I understand loops and arrays.
It compiles, and runs as expected, with the exception that if a user inputs something that isn't a number the program races through the first if statement infinitely without a chance to add a new input. I really can't see how to fix this.
I think the issue is that chosenSquare is an integer as it needs to be compared to values, but cin can take anything in. Expected behaviour would be to check if the input is an integer between 0 and 8 (the 9 spaces on the board), and if not return a message and repeat, waiting for a new input.
Is there a simple fix for this? I'm trying to avoid specialist packages and namespaces for now while I grok the basics. I've looked at similar problems but don't follow them.
Thanks.
Code snippet:
// Input loop
bool valid = false;
while (valid != true)
{
int chosenSquare = 0;
cout << "Player " << currentPlayer << ", enter a number between 1 and 9:" << endl;
cin >> chosenSquare;
chosenSquare--; // For array indexing
if ((chosenSquare < 0) || (chosenSquare > 8)) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
continue;
}
else if ((board[chosenSquare] == currentPlayer) || (board[chosenSquare] == lastPlayer))
{
cout << "Square not availible. Try again." << endl;
continue;
}
else
{
board[chosenSquare] = currentPlayer;
valid = true;
break;
}
}
There are a couple of things culminating causing this.
The first is that when an alpha character is put into the console, the error bit is set, and 0 is written to the variable you're writing to:
The behavior you want to observe changed in 2011. Until then:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
But since C++11:
If extraction fails, zero is written to value and failbit is set. [...]
(From cppr.)
That means chosenSquare is 0 after the read, so chosenSquare-- makes it -1. -1, as you know, is less than 0, so the first if-statement is true.
As to why it stays this way infinitely, you need to clear the fail-bit.
So I changed the first loop after a bit of reading and experiementation:
if (cin.fail()) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
cin.clear();
cin.ignore();
continue;
}
This works, but I can't figure out what it's actually doing.
Could anyone elaborate?

Checking input on a char variable

I'm trying to validate input for a quit/return question in my program so the user is forced to enter either 'r' or 'q'.
I have managed to get it almost working. The problem is if the user enters 'r' or 'q' at the beginning followed by random letters then the program accepts that input. Any ideas on how to get the program to allow only a single 'r' or 'q' ?
void exit()
{
char choice;
bool badInput;
do
{
cout << "Press 'r' to return to the menu\nPress 'q' to quit the program\n\n" << endl;
cin >> choice;
badInput = cin.fail();
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while (badInput == true && choice == 'r' && choice == 'q' && (cin.peek() == EOF));
if (choice == 'q')
{
system("CLS");
cout << "Bye!\n";
system("PAUSE");
}
else if (choice == 'r')
{
system("CLS");
main();
}
else
{
exit();
}
}
You've got a very strange way of approaching this problem that's got a lot of issues. In particular, creating a function called exit() is problematic since that's a core function, and calling it recursively to try and get input is likewise not a good plan. You already have a loop, you just need to use it more effectively.
Likewise, main() is called automatically and you should never have reason to call it manually.
Here's a first pass rewrite:
void getInput()
{
char choice;
while (true)
{
cout << "Press 'r' to return to the menu\nPress 'q' to quit the program\n\n" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin >> choice;
switch (choice)
{
case 'q':
system("CLS");
cout << "Bye!\n";
system("PAUSE");
exit(0);
break;
case 'r':
system("CLS");
doMain();
break;
}
}
}
This obviously needs more work, but at least should theoretically function. In your original code you're demanding that the input value be simultaneously two different things which is an impossibility, that code will never work.
I'd also encourage you to stop doing things like system("CLS") and system("PAUSE") and instead do something in C++ natively. That's not portable code and it's terribly clunky as it depends on commands from 1980s DOS.
Handling the input
Most implementation use a buffered cin, so that input will only be returned once the user press enter. If this is not acceptable to you, you'll have to use OS-dependent functions.
If it's ok for you, then if you read a char, only the first one will be handed over: the remaining chars until the enter will wait for subsequent reads. Therefore, instead of reading a single char, I propose you to read a full line into a string:
void want_exit()
{
const string message="Press 'r' to return to the menu\nPress 'q' to quit the program\n";
string line;
cout << message << endl;
while (getline(cin, line) && line.length()!=1
&& tolower(line[0])!='y' && tolower(line[0])!='n')
{
cout << "Invalid input" <<endl << message <<endl;
line.resize(0);
}
Now line contains either a single valid char, or it is empty (in case of premature eof, meaning, that there was an input redirection and that there will anyway be no more input).
Processing the input
You can't call recursively main(): you should instead return from the function, and organize the calling function so to continue the process
if (line.empty() || tolower(line[0])!='y' ) {
system("CLS"); // This is non portable
cout << "Bye!\nPress enter...";
cin.getch(); // as good as system("PAUSE");
std::exit(0); // be aware of the naming issue !
}
return;
}
The calling function (main() ?) would then use it in a loop:
while (...) {
...
if (...)
want_exit();
}

while statement is unable to read the correct char input

hi i am new to c++ and i dont understand why my while statement doesnt work now. it was working when i tried to do it earlier.
Full code is available at: http://pastebin.com/aeH5fKwh
basically here is the while loop (i excluded all the unnecessary parts, i left the inside of the while loop intact for viewing purpose)
int main()
{
unsigned int seed;
char input;
bool done;
for (int round = 0; round < 5; round++)
{
done = false;
cout << "\nEnter seed: ";
cin >> seed;
cout << "\nRound 1" << endl;
while(!done)
{
cout << "\nDo you wish to draw another card [y][n]: ";
cin >> input;
while (input != 'y' && input != 'n')
{
cout << "Invalid input! Please enter [y][n]!" << endl;
cin >> input;
}
if (input == 'y')
{
dealExtra(playerHand, deck, gameInfo);
cout << "Your cards are ";
printHand(playerHand, gameInfo.playerCardCount);
}
else
done = true;
}
}
cout << endl;
return 0;
}
when i try entering anything that is not 'y', 'n', it will tell me that my input is invalid. But when i try to enter 'y' or 'n', it kinda just ignored it and nothing else happened.. i checked with cout statement and found that it manage to get into the if (input == 'y') statement, but it doesnt seem like it is doing anything else. Everything was fine till 20 minutes ago and i really couldnt figure out whats wrong.
Edit: i ran another test using "cout << '[' << input << ']' << endl;".. it seems like the program is able to get my first input, but then it just hangs there afterwards.. what i get is something like:
Do you wish to draw another card [y][n]: y
[y]
y
y
y
y
I compiled this on linux terminal using g++
if extra codes is needed, i'll edit and add them.. thanks!
When you ask for input from the console, most implementations buffer characters until a newline key is pressed.
After the newline is received, the first character of the buffer is returned. The newline still remains in the buffer as well as any extra characters.
In your case, the second cin >> input statement will read the newline from the buffer.
As an experiment, try entering "frog" and single step through your program. This should illustrate the case of residual characters in the buffer.
Try cin.ignore(1000, '\n') after the first cin >> input. The ignore method will eat up any remaining characters in the buffer until the newline is found.
Make below statements inactive
dealExtra(playerHand, deck, gameInfo);
printHand(playerHand, gameInfo.playerCardCount);
and check if it works, then try making one of the above statements active alternately to find out in which function the flow is getting lost. And so on.
If you feel lazy to run a debugger, and plan to use cout<< statements to find a hanging call, you should flush you cout:
( cout << "I am here and going to hang" ).flush() ;
Otherwise you can't see recent output just because it's still in the output buffer. Try this and you well might see what call hangs your program.
You have an infinite loop inside checkComputerHand:
bool done = false;
while(!done)
{
if(sum == 11 && checkAce == true)
{
computerHand[aceLocation].value = 11;
done = true;
}
if(sum > 11 && checkAce == true)
{
computerHand[aceLocation].value = 1;
done = true;
}
// What if checkAce wasn't true? Infinite loop!
}
Also, the first two lines of newGame do not make any sense:
void newGame(Card playerHand[], Card computerHand[], Statistics &gameInfo)
{
playerHand = '\0';
computerHand = '\0';
// ...
}
Array parameters are silently rewritten by the compiler as pointer parameters. So all you're doing is assigning the null pointer to those local pointers. Probably not what you intended...

User Input of Integers - Error Handling

I'm having some trouble with certain input areas of my program. There are a few parts where the user inputs a specific integer. Even if they enter the wrong one that's all fine and dandy, but I noticed if they enter anything not of integer type like 'm' then it will loop the error message repeatedly.
I have a couple functions that have integer input in them. Here's one for an example.
void Room::move(vector<Room>& v, int exone, int extwo, int exthree, int current)
{
v[current].is_occupied = false;
int room_choice;
cout << "\nEnter room to move to: ";
while(true)
{
cin >> room_choice;
if(room_choice == exone || room_choice == extwo || room_choice == exthree)
{
v[room_choice].is_occupied = true;
break;
}
else cout << "Incorrect entry. Try again: ";
}
}
There is still a problem in your "solved" code. You should check for fail() before checking the values. (And obviously, there is the problem of eof() and IO failure as opposed to format problems).
Idiomatic reading is
if (cin >> choice) {
// read succeeded
} else if (cin.bad()) {
// IO error
} else if (cin.eof()) {
// EOF reached (perhaps combined with a format problem)
} else {
// format problem
}
You can use cin.good() or cin.fail() to determine whether cin could successfully deal with the input value provided. You can then use cin.clear(), if necessary, to clear the error state before continuing processing.
For a even simpler way, you can use ! operator like this:
if ( !(cin >> room_choice) )
{
cin.clear();
cin.ignore();
cout << "Incorrect entry. Try again: ";
}