How to ignore wrong cin input in C++? - 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
}

Related

While condition: How to allow comparison between non-integer/double user input and integer limits

Objective: Run a while loop that will repeat until the user inputs an integer between 1-3 (inclusive). So if an integer that is smaller than 1 or bigger than 3 is inputted or any character or string is inputted, the loop repeats.
My noob knowledge: I know how to compare user input when it is an integer, but when it is a char or string datatype input all I get is an infinite loop. Plus I declared the inputtable variable as an integer, so not sure how to go on about this.
I've done some Google searches but can't seem to find a question similar enough to mine.
Advice is highly appreciated :)
Code below:
int Decision1 = 4;
while ( Decision1 < 1 || Decision > 3)
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << "\n\n";
}
int Decision1;
while(std::cin >> Decision1) {
if(Decision1 >= 1 && Decision1 <= 3) break;
// todo
}
You can use ASCII codes for checking number or character.
#include <iostream>
int main() {
char Decision1 = '0';
while ( (Decision1 < 49 && Decision1 >=47) || (Decision1 >51 && Decision1 <=57 ))
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << Decision1;
std::cout << "\n";
}
}
I hope helpful for you.
Keep in mind: when you read input from std::cin you're reading text that's typed at the console. The stream extractor tries to convert that text to the target type. That is, in
int i;
std::cin >> i;
the >> operator looks for digit characters and figures out what value those characters represent. If the characters can't be converted to an integer value the extraction fails. Streams have a conversion to bool that tells you whether the stream is in a good state, or whether an attempted operation failed. So:
int i;
if (std::cin >> i)
std::cout << "got a value!\n";
To write a loop that prompts for valid input you need to reverse the test:
int i;
while (!(std::cin >> i) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To also check that the value is in the required range, just do it:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To clear the input stream, you have to reset its internal flags. You do that with std::cin.clear();. And, depending on what you think was typed in, you probably want to get rid of any additional characters that the user typed. You do that with std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n'). That tells the stream to discard character until it reaches a newline (press ENTER), or until it has read a huge number of characters.
Putting it all together:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
std::cin.clear();
std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Yes, this clears the stream state and flushes the input when the input was a valid integer but out of range; that's harmless. It's a waste of time, but the speed of keyboard input is limited by how fast the user types, which is much slower than anything that the code in this loop does.

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...

How do I allow different amounts of input in c++

Assume all variables exist (didnt bother declaring them all here)
if(input=='R') goto restart;
if(input=='X') exit(0);
if(input=='D') moveRight(edgeLength, board, score);
if(input=='S') moveDown(edgeLength,board, arrSize);
if(input=='A') moveLeft(edgeLength,board, arrSize);
if(input=='W') moveUp(edgeLength,arrSize,board);
if(input=='P')
{
cin>> number>>position;
board[position]=number;
}
This input is put into a loop, so the user is asked for input so long as this game is in play.
My goal is to allow for input such as
p 3 50
to place the number 50 at index position 3.
With my current code, I have to type 'p' press enter, then the next two numbers.
However, id like the program to detect 'p 3 50' (enter) in one go, as 'D'(enter) signifies moveRight.
I hope I'm being clear in my question.
cin >> input >> number >> position;
if(input=='R') goto restart;
else if(input=='X') exit(0);
else if(input=='D') moveRight(edgeLength, board, score);
else if(input=='S') moveDown(edgeLength,board, arrSize);
else if(input=='A') moveLeft(edgeLength,board, arrSize);
else if(input=='W') moveUp(edgeLength,arrSize,board);
else
{
//whatever statements for last condition;
}
If you want to capture all three input at once, you can get the input first, then execute the respective actions according to the received inputs.
Added: Using if or else-if depends on situation. From what I see here in your code snippet, else-if is better than if because you can only have one input type everytime. Once matching character is found, (example 'D'), it will stop reading the codes below (which should be the way as it is unnecessary to check the rest of the conditions whether input is 'S' or 'A' or 'W' anymore since you already got the input). Makes your code fun slightly faster too, by preventing unnecessary checking on the conditions.
Proof Of Concept:
//Example
void fncOne()
{
cout << "This is function one" << endl;
}
void fncTwo()
{
cout << "This is function two" << endl;
}
int main()
{
char input;
int number, position;
cin >> input >> number >> position;
if (input == 'A') fncOne();
else if (input == 'B') fncTwo();
}
Input: A 3 5
Output: This is function one
Well, first you're going to want to get user input as a string rather than individual types.
std::string input;
std::cin >> input;
then you'll want to parse that string based on how many words for key words/characters.
e.g.
std::vector<std::string> words;
std::stringstream stream(input); std::string temp;
while(stream >> temp)
words.push_back(temp);
if(words.size() == 3){
if(words[0][0] = 'p'){
int number = std::stoi(words[1]);
int position = std::stoi(words[2]);
board[position] = number;
}
else
... get input again ...
}
else if(words.size() > 1){
... get input again ...
}
else{
char c = words[0][0];
if(c == 'w')
moveUp(edgeLength,arrSize,board);
else if(c == 's')
moveDown(edgeLength,board, arrSize);
else if(c == 'a')
moveLeft(edgeLength,board, arrSize);
else if(c == 'd')
moveRight(edgeLength, board, score);
else if(c == 'x')
exit(0);
else if(c == 'r')
goto restart;
else
... get input again ...
}
Of course this is only one way if you want to type one string then press enter only once.

Failed Input help, Int and Char, C++

I am trying to determine if the user enters something other than a character, and specifically, that they only enter m or s. See code below.
Note:
filingStatus is a char
do
{
cout << "Please enter your filing status (s for single, m for married)" << '\n';
cin >> filingStatus;
if (cin.fail())
{
cin.clear();
dataTest = 1;
cout << "Error, please enter a valid input!" << '\n';
double dummyDouble;
cin >> dummyDouble;
if (cin.fail())
{
cin.clear();
cin >> dummyString;
}
}
else
{
if (filingStatus == 'm' || filingStatus == 's')
{
dataTest = 0;
}
else
{
cout << "Error, please enter either m or s!" << '\n';
dataTest = 1;
}
}
} while (dataTest == 1);
Here is the problem, if I enter 1000 for example, the input doesn't fail. It instead stores the 1 in the char, and since 1 is neither m or S, it loops again, then it puts the 0, loops again, puts another 0, etc.
My understanding was it would fail when it sees that a integer is being stored in a char, but obviously it isn't failing.
My question is:
Why isn't the input failing? How can I change it so if someone enters a string, or number that it fails?
The input isn't failing, because '1' is a character. Digits are a subset of characters.
Read into a std::string. Then test whether that string consists of a single character from your desired range.
Note however, that reading into a string using >> stops at the first white space. To prevent this and read the whole line instead, read using std::getline().
I am assuming that fillingStatus is of char type.
Now even if you enter a numeral say '1' or '0', it is read as a char. Hence cin does not fail. It just keeps on looping as per your code.
Also, while reading an invalid char, you should be careful of clearing the input buffer because the return character '\n' stays along with other characters in the input buffer.
I would do it something like the following:
while ( !(cin >> fillingStatus) || (filingStatus != 'm' && filingStatus != 's') ) {
cout << "Error, please enter either m or s!" << '\n'; // error message
cin.clear(); // clear the error flag
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // ignore all invalid previous input
}
One way could be to change the fillingStatus to string and get only the first character of that string and see if it fails or not.
Alternatively, there used to be a method for getting a character input, getche() I think (it has been many years since I worked in C++ so don't exactly recall)...you maybe able to use that too.
Thanks
Since you are only reading the input one character at a time, your are essentially unable to tell that the user has input more and it is being held until you read more from the input stream.
Using a string to read a line of data at a time and having the program react to that string as a whole will solve your problem.
std::string filingStatus ;
while(!(cin >> filingStatus ) || ( filingStatus != "m" && filingStatus != "f") )
{
cin.clear();
std::cout << "Error, please enter either m or s!" << '\n';
};

Problem with input in c++

I have a very basic question i want to take integer input in certain range from user. if the user gives some string or char instead of integer. then my program goes to infinite loop.
my code is some what like that
cin >> intInput;
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
cin >> intInput;
}
I am only allowed to use c++ libraries not the c libraries.
As mentioned in the possible duplicate, you should check the state of cin on each loop.
Possible implementation:
if(cin >> intInput)
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
if(!(cin >> intInput)){ break; }
}
Very ugly code, just trying to illuminate the answer which is to check the state of cin.
The solution to this answer is to always read lines from the standard input.
std::string input; int value = 0;
do
{
// read the user's input. they typed a line, read a line.
if ( !std::getline(std::cin,input) )
{
// could not read input, handle error!
}
// attemp conversion of input to integer.
std::istringstream parser(input);
if ( !(parser >> value) )
{
// input wasn't an integer, it's OK, we'll keep looping!
}
}
// start over
while ((value > 4) || (value < 1));
#include <locale>
..
if(!isalpha(intInput)) {
..
}
Note, this won't work if, for example the user enters a "+" but maybe it will put you in the right direction..