I am currently working on a c++ program and I want to check to see if the input the user is making is valid. Currently my code works if the user inputs the proper input or if the user inputs a small incorrect number my pogram will tell the user that the input is invalid. Now my problem is that when the user inputs multiple characters/letters or a large number that has 9 or more digits in it my program goes into an infinate loop giving them the error message. The following is my code:
//for (;;)
while (flag== false)
{
cin >> Input;
if (Input <= choice.size()-1)
{
flag = true;
// break;
}
else
{
cerr << "Input <" << Input << "> is Invalid, Please Choose a Valid Option\n";
userInput = 0;
}
}
As you can see I have also tried doing an infinate for loop but it gives me the same results.
In my code i am printing a vector to the screen. Basicly the user it picking the vectors value to use it.
I am open to any suggestions. Thanks
If the user types in something that can't be read into Input (it's not clear from your code what type Input is), that input will get stuck in the input stream and each iteration of the loop will keep failing to read in the input until you clear the stream.
You need to clear the stream flags and get rid of whatever bad input is waiting in the stream after each failure to read. Try something like this:
while(!(cin >> Input) || Input <= choice.size()-1)
{
cerr << "Input <" << Input << "> is Invalid, Please Choose a Valid Option\n";
cin.clear(); // Clears the input stream fail flag
cin.ignore(100, '\n'); // Ignores any characters left in the stream
}
Related
I am having difficulty figuring out how to get my loop to end, when an incorrect input is given. Every combination I could think of, to end the loop hasn't worked. What could be the next step to figure this out. The code is attached below. The next step, when the correct input is given, is to increment the number.
int main(){
int startingNumber;
int endingNumber;
int incriment;
cout<<"Enter a starting number\n";
cout<<"**";
while(!(cin>>startingNumber))
{
cout<<"Error: invalid entry\n";
cin.clear();
cin.ignore (500 ,'\n');
break;
return 0;
}
cout<<"Enter a ending number\n";
cout<<"**";
while(!(cin>>endingNumber))
{
cout<<"Error: invalid entry\n";
cin.clear();
cin.ignore (500 ,'\n');
}
}
First, good job on looking to validate the stream-state after input and before making use of the variable filled. Far too many questions simply ignore validation.
It looks like what you are trying to do is to require valid input from the user, and if a non-integer value is entered resulting in failbit being set, you want to clear the error bit, ignore the offending character and require the user to try again. That is a proper approach.
Where your logic breaks down is thinking you need to break if failbit is set. Just the opposite. To handle and recover from an invalid input, you want to loop-continually and break only when valid input is received. That way you validate the input, and if you have what you need, you break the read-loop, otherwise you handle the error and require the user to try again.
Ignoring increment for now, it looks like you wanted to:
#include <iostream>
#include <limits> /* for numeric limits */
int main(){
int startingNumber;
int endingNumber;
while (true) { /* loop continually until valid input received */
std::cout << "Enter a starting number\n** "; /* prompt */
if (std::cin >> startingNumber) { /* validate */
break; /* break on good */
}
/* handle error */
std::cerr << " Error: invalid entry\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
}
while (true) { /* ditto */
std::cout << "Enter a ending number\n** ";
if (std::cin >> endingNumber) {
/* add any additional needed criteria */
if (endingNumber == startingNumber) {
std::cerr << " Error: must not be startingNumber.\n";
}
else {
break;
}
}
else { /* condition cin.fail error since == check added */
std::cerr << " Error: invalid entry\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
}
}
std::cout << "startingNumber : " << startingNumber <<
"\nendingNumber : " << endingNumber << '\n';
}
(note: you would also want to check for eofbit and exit gracefully if the user enter a manual EOF with Ctrl + d (Ctrl + z on windows). Canceling input is a valid act by the user. Consider also checking for badbit in the off-chance there was a terminal error that was unrecoverable -- not likely -- up to you)
Note also the additional condition in the second input routine that checks if startingNumber == endingNumber. This is by way of example, presuming you don't want a zero increment later. The point being you can tailor your input routine to handle as many contingent cases as your code needs. You would much rather over-validate than let a corner-case that tanks your code slip through.
One additional consideration is calling std::cin.ignore() after the good input is received to deal with any trailing characters. (e.g. "20 more fleas" would be valid input but leave " more fleas" in the input buffer. In the event there is nothing to ignore, std::ignore() will return eofbit that you will need to .clear(). See: std::basic_istream::ignore This would be another simple addition that would strengthen your input routine.
Example Use/Output
Exercising the code you could do:
$ ./bin/startendno
Enter a starting number
** my dog has 10 fleas
Error: invalid entry
Enter a starting number
** 10
Enter a ending number
** 10
Error: must not be startingNumber.
Enter a ending number
** foo
Error: invalid entry
Enter a ending number
** 20
startingNumber : 10
endingNumber : 20
Look things over and let me know if you have further questions.
I am fairly new to C++ and need some help on a tic-tac-toe project that I am working on. Everything is completed except for the input, which I am having a lot of trouble with. Relevant pieces of my code and some input that breaks the program is below.
cout << "Your move. Where would you like to play? Enter the row. Note that the row numbering starts at 0." << endl; // Ask for user input for move
if(started)
{
cin.clear(); // Clear cin fail bit
cin.sync(); // Sync cin buffer to get rid of lines left over
}
cin >> moveX; // Get row input from user
cin.ignore(10000, '\n'); // Ignore rest of line
cin.sync(); // Sync cin buffer to get rid of lines left over
if(validateMoveX(moveX) == -1) // If the move was not validated
{
cout << "TOO MANY INVALID ATTEMPTS...EXITING" << endl << endl; // Tell the user that there were too many invalid attempts
return ' '; // Return a space to main
}
cout << "Your move. Where would you like to play? Enter the column. Note that the column numbering starts at 0." << endl; // Ask for user input for move
cin.sync(); // Sync cin buffer to get rid of letters stuck in buffer
cin.clear(); // Clear cin fail bit
cin >> moveY; // Get the column input from user
cin.sync(); // Sync buffer to get rid of letters left over
cin.clear(); // Clear cin fail bit
cin.ignore(10000, '\n'); // Ignore rest of line
if(validateMoveY(moveX, moveY, miniBoard) == -1) // If the move was not validated
{
cout << "TOO MANY INVALID ATTEMPTS...EXITING" << endl << endl; // Tell the user that there were too many invalid attempts
return ' '; // Return space to main
}
Above is my code from the function that actually plays the game and calls all the other functions that are used in my program. I think this is where the issue lies, but I am not certain. The issue could also be in my Y-input validation function (probably the cin.ignore() line just before cin >> moveY). I think my X-input validation function is fine (again, not 100% sure)
Code from my function to validate user input for rows: https://pastebin.com/v3VtLbJ4
Code from my function to validate user input for columns: https://pastebin.com/cqfWTc05
Test data that breaks program:
Row input: 1 2
Column input: asdjfasjldksk sdlfasl ljk (basically random input)
Problem: Program reads this as "Play a move at 1, 0"
OR
Row input: put something random
Column input: 100000000000
After the program asks to re-enter input for the column: 1
Problem: The second "1" is not read
I'm writing a program where I get an integer input from the user with cin>>iUserSel;. If the user puts in a letter, the program goes to an infinite loop. I tried to prevent that with the code below, but the program goes to an infinite loop and prints out "Wrong! Enter a #!". How can I fix my program?
cin>>iUserSel;
while (iValid == 1)
{
if (cin.fail())
{
cin.ignore();
cout<<"Wrong! Enter a #!"<<endl;
cin>>iUserSel;
}//closes if
else
iValid = 0;
}//closes while
I found some information on this at Correct way to use cin.fail() and C++ cin.fail() question
, but I didn't understand how to use them to fix my issue.
When cin fails, you need to clear the error flag. Otherwise subsequent input operations will be a non op.
To clear the error flags, you need to call cin.clear().
Your code would then become:
cin >> iUserSel;
while (iValid == 1)
{
if (cin.fail())
{
cin.clear(); // clears error flags
cin.ignore();
cout << "Wrong! Enter a #!" << endl;
cin >> iUserSel;
}//closes if
else
iValid = 0;
}//closes while
I would also suggest you change
cin.ignore();
to
cin.ignore(numeric_limits<streamsize>::max(), '\n');
In case the user enters more than one letter.
The problem you are having is that you don't clear the failbit from the stream. This is done with the clear function.
On a somewhat related note, you don't really need to use the fail function at all, instead rely of the fact that the input operator function returns the stream, and that streams can be used in boolean conditions, then you could do something like the following (untested) code:
while (!(std::cin >> iUserSel))
{
// Clear errors (like the failbit flag)
std::cin.clear();
// Throw away the rest of the line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Wrong input, please enter a number: ";
}
Here's what I would recommend:
// Read the data and check whether read was successful.
// If read was successful, break out of the loop.
// Otherwise, enter the loop.
while ( !(cin >> iUserSel) )
{
// If we have reached EOF, break of the loop or exit.
if ( cin.eof() )
{
// exit(0); ????
break;
}
// Clear the error state of the stream.
cin.clear();
// Ignore rest of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Ask more fresh input.
cout << "Wrong! Enter a #!" << endl;
}
I tried to use if(!cin) to validate if the user input really is an integer. However my programm then just goes into an infinite loop never asking vor new input
do{
cin >> temp->data;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}while(correct==false);
Would be great if someone could help me :)
When std::cin fails to read the input, the appropriate error flags are set. Therefore you want to reset the flags using std::cin.clear() so that the next input operation will work correctly and then skip everything until the new line using std::cin.ignore(..) in order to avoid similarly formatted input.
while (!(std::cin >> temp->data))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\nPlease enter a number!" << std::endl;
}
std::numeric_limits<std::streamsize>::max() returns the max amount of characters a stream can hold so that the whole line is guaranteed to be ignored.
If you want to do that kind of check, read the data from cin to a string and convert the string to a number:
string str;
do{
cin >> str;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
else{
istringstream stream(str);
stream >> temp->data;
if(!stream){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}
}while(correct==false);
Use cin.fail() to check whether the user entered correct input. cin.fail() returns true if the last cin command failed, and false otherwise. Moreover, your loop is likely to be infinite, so you must also state an else where you will set the check flag correct to true. Thus, to invalidate the loop's condition and exit the loop in the case user entered correct input (see code below):
do{
cin >> temp->data;
if(cin.fail()){
cin.clear();
cin.ignore(10000, '\n');
cout << "Please enter a Number!" << '\n';
correct=false;
} else {
correct=true;
}
}while(correct==false);
Your 'correct' variable actually doesn't do anything the way you are using it. It's not possible to exit the loop without correct being true; so you could do away with it, and just use a loop-exiting command when you have read the number.
Also, none of the answers posted so far handle the input being closed. They would go into an infinite loop in that scenario.
// A loop; we will break out when we successfully read a number.
while ( 1 )
{
// Prompt for a number and read it
cout << "Please enter a Number!" << endl;
cin >> temp->data;
// Exit loop if we successfully read
if ( cin )
break;
// Check to see if we failed due to the input being closed
if ( cin.eof() )
{
cerr << "End of input reached.\n";
return 0; // depends what your function returns of course
}
// reset the error condition that was caused by trying to read an integer and failing
cin.clear();
// discard anything they previously typed
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
Moving on from this, a good design would be to actually have this code be an entire function in itself. Then you can call the function whenever you need to get a number safely, without needing to duplicate code. The function declaration might be:
void input_number(int &the_number, std::istream &in, std::string prompt);
which would output the_number, and it would handle end-of-file either by throwing an exception, or by relying on the caller to check for !cin, or even by returning a bool; whatever fits in best with your error handling overall.
For one, if you put a "!" before a condition in an if statement. That's supposed to be a "not" operator.
Hi i'm newish to C++ but i have a little problem which is i have to stop the user entering letters in a number section. I have made an attempt which works but its dodgy, because it will allow the user to continue then will tell them they have got something wrong and to restart the application. How do i validate it to bring up an error message telling them thats not a number and let them re enter a number?
Here is the code:
double Rheight;
do
{
cout << "Enter height of the room. " << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
cout << "WARNING: If you enter a letter the program will exit." << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
cin >> Rheight;
}
while (Rheight > 20 || Rheight == 0);
Ask if you need to see more code.
There are basically two components to the answer:
Detecting that the input failed.
Cleaning up after a failed input.
The first part is rather trivial: you should always test after input that the stream is in a good state before using the input. For example:
if (std::cin >> value) {
// use value
}
else {
// deal with the input error
}
How to deal with the input error depends on your needs. When reading a file you'd probably abort reading the entire file. When reading from standard input you can ignore just the next character, the entire line, etc. Most like you'd want to ignore the entire line. Before doing so you'll need to put the stream back into a good state:
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
The first line clears the stream's error flags and the second line is a magic incantation ignoring as many characters as necessary until a newline got ignored.
To check if the input was valid you can use
if(!(cin >> Rheight))
{
cout << "Please input a valid number!" << endl;
continue;
}