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;
}
Related
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
When it comes to creating a program based on a set of instructions, I do pretty well in designing the pseudo-code, implementing the actual code. What I feel like I lack is checking for users' input (whether it's valid or invalid). As I practiced programming, I created my own way for checking for validating users' input. But the code is lengthy and I feel like it's insufficient (I'll explain why). I wanted to know if there is a better way to check for users' input. And how do other programmers implement their code.
This is how I validate users' input:
if(cin.fail()) {
cout << "Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
// I didn't know how to skip a line while in code
while(input < 0) {
cout << "Invalid Input" << endl;
cout << "Enter radius: " << endl;
cin >> input;
if(cin.fail()) {
cout << "Error: Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
}
The reason why I exit out when cin fails to store the value into the variable separately (line 1 - 5, line 11 -15) is because if I add the cin.fail() to the while condition and attempt to input a letter, it begins a infinite loop. I did a little research and I saw you have to cin.sync(), then cin.clear(). But I still get the infinite loop.
Here is the code:
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 || cin.fail());
If I'm doing something wrong, it would very helpful to see better ways to validate user's input.
I would not recommend using std::cin, since it leaves all remaining user input after the first found instance of whitespace in the input buffer. This will create problems unless you remove the remaining characters using cin.ignore(). It is generally seen as better practice to use getline(), which will get all the characters up to the newline character. If you do choose to use std::cin, you will need to use cin.ignore() to remove the remaining characters, and cin.clear() to reset cin's fail bit so the while conditional will work properly the next time through the loop.
Below is how I would solve the problem. It uses getline() to get all the characters, and a stringstream to convert the string to an int. Notice you need to clear the stringstream's fail bit just like with cin to make sure the conditional works correctly when you do ss >> result in the while conditional.
std::cout << "Enter radius: ";
getline(std::cin, input);
std::stringstream ss(input);
while(!(ss >> result)) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
getline(std::cin, input);
ss.clear();
ss << input;
}
Below I'll also include some code to solve the problem using std:cin. I still recommend using getline() though. Note: std::numeric_limits::max() is used to specify how many characters to remove from the input buffer. Using this instead of your own arbitrary number is a better practice, since you can't know for certain how many characters the user will enter. cin.ignore() will remove all the characters up to the given number or until it reaches an instance of the character provided as its second parameter, which in this case is newline ('\n').
std::cout << "Enter radius: ";
std::cin >> result;
while(std::cin.fail()) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin >> result;
}
The problem of input validation is an easy form of parsing.
There are language-classes (in the field of formal language theory) that express the complexity of your input. Those classes are called regular, context-free, and turing-complete.
You have to consider all your possible inputs, that your program might receive and decide whether your program should accept them or not. The language classes help you to decide what kind of input validation you need.
if the language is regular (as it is in your case) you can use regular expressions to validate the input.
A context-free language for example would be a math-formula. You cannot count the number of parentheses with a regular expression. Therefore it is impossible to check ((a+b) * (c+d)) has the right amount of parentheses with a regular expression.
Up to now these are hints on what you should be doing, when programming comes more naturally to you.
For the sake of simplicity well do a very constrained regular expression like parsing by hand.
what you actually want to do in pseudo code:
do {
std::cout << "Please enter radius: ";
line = read_a_line_from(std::cin) // separated by '\n' the newline
if (false == really_read_a_line(line)) {
/* error handling for std::cin, dealing with i.e.: the fail bit */
break; /* exit the loop */
}
if (line == "exit") { // give the user an explicit exit, to quit gracefully
exit(SUCCESS); /* exit the program */
}
if (false == is_a_number(line)) {
/* we read something that isn't a number */
/* we should tell the user he should do as we asked */
continue; /* jump back to the beginning of the loop */
}
unsigned num = convert_number(line);
unsigned area = calculate_area(num); /* do something with your input */
} while (true);
exit(FAILURE);
The code here is not too specific on purpose that you see what you could be doing in places, still leaving out the actual implementation (for your exercise). Please note that a simple way of checking whether a line is actually a number is by converting. However not all things to parse should be checked for validity and processed at the same time.
See Also (especially the examples):
http://en.cppreference.com/w/cpp/string/basic_string/getline
http://en.cppreference.com/w/cpp/string/basic_string/stol
how to check if given c++ string or char* contains only digits?
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 && cin.fail());
I used cin.get() to get the program to pause and wait for user input, and it works fine. The moment I put it in an if statement, it just skips that "wait" period and continues on with the code? How can I solve this. Here is the section that is not working.
do
{
cout << "\n\n\nEnter the number of one of the following and I will explain!\n";
cout << "1.integer 2.boolian 3.floats 4.doubles 5.character";
cout << "\n\n[when you are done type 'done' to continue]\n\n";
cin >> option;
if (option = 1);
{
cout << "\nInteger is the variable abbreviated as 'int' this allows C++ to only";
cout << "\nreadwhole and real numbers \n\n";
cin.get(); //this is the part where it just skips.. it should wait
}
} while (var = 1);
The problem is that cin >> option will extract whatever integer is in the input stream but will leave the following newline character (which is there from hitting enter after typing in the value). When you do cin.get() it is simply extracting that newline character which is already there. Like so many other questions like this, the solution is to empty the input stream after you've extracted into option:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You are also using assignment (=) where you should be comparing for equality (==).
I am a beginner programmer learning c++. I am having a nagging issue with the cin command.
In the program section below, if I enter a wrong type at the 1st cin command, the program will not execute any of the following cin commands at all, but will execute the rest of the program.
//start
#include <iostream>
using namespace std;
int main()
{
int x=0;
cout << endl << "Enter an integer" << endl;
//enter integer here. If wrong type is entered, goes to else
if (cin >> x){
cout << "The value is " << x << endl;
}
else {
cout << "You made a mistake" << endl; //executes
cin.ignore();
cin.clear();
}
cout << "Check 1" << endl; //executes
cin >> x; //skips
cout << "Check 2" << endl; //executes
cin >> x; //skips
return 0;
}
//end
Instead of the if else, if i put the same concept in a loop
while (!(cin >> x))
the program goes into an infinite loop upon enterring a wrong input.
Please help me explain this phenomenon, as the text book i am following says the code typed above should work as intended.
Thank you
cin is an input stream. If an error occurs cin goes into a let's call it "error occured" state. While in this state no character input can be made, your request to collect a character from the input stream will be ignored. With clear() you clear the error and the input stream stops ignoring you.
Here is the ignore function prototype
istream& ignore ( streamsize n = 1, int delim = EOF );
This function gets characters from the input stream and discards them, but you can't get any character if your stream is ignoring you, so you have to first clear() the stream then ignore() it.
Also, a note on the side: If someone inputs, for example "abc", on the first input request your cin gets only one character that is 'a' and "bc" stays in the buffer waiting to be picked up, but the next call to cin gets the 'b' and 'c' stays in the buffer, so you again end up with an error.
The problem with this example is that the cin.ignore() if no arguments are handed to it only ignores 1 character after you clear(). and the second cin gets 'c' so you still have a problem.
A general solution to this problem would be to call
cin.ignore(10000, '\n');
The first number just has to be some huge number that you don't expect someone would enter, I usually put in 10000.
This call makes sure that you pick up all the characters from the false input or that you pick up every character before the enter was pressed so your input stream doesn't get into the "error occurred" state twice.
You may also want to try
if ( std::cin.fail() )
as a backup to prevent a crash due to input of the wrong type when prompted
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
}