Input validation in C++
Inputs have to be validated before allowing any kind of processing or operations to be performed on it. This is extremely important because, an unhandled wrong input might have the complete ability to crash a system. C++ has some good validation techniques that can be used to validate most kind of inputs. This post discusses some of the techniques and its shortcomings and what could be done to improve the quality of validation.
Now, consider a program has to accept only integer inputs and reject all the others. So, the developer would have declared to store the integer value in say “int a;”. So “a” will store the input value.
When the user input is accepted using the “cin>>a” statement, we can use the inbuilt methods surrounding the “cin” statement to test its status.
Here is a sample program: –
</p> #include #include using namespace std; int main() { int a; <p style="text-align: left;"> cout<<"Enter an integer number\n"; cin>>a; while(1) { if(cin.fail()) { cin.clear(); cin.ignore(numeric_limits::max(),'\n'); cout<<"You have entered wrong input"<<endl; cin>>a; } if(!cin.fail()) break; }</p> <p style="text-align: left;">cout<<"the number is: "<<a<<endl; return 0; }</p> <p style="text-align: left;">
From the above example, the various functions are used to validate the input like the cin.fail(), cin.ignore(), etc. The various functions of these methods are :
function |
Description |
cin.fail() | This function returns true when an input failure occurs. In this case it would be an input that is not an integer. If the cin fails then the input buffer is kept in an error state. |
cin.clear() | This is used to clear the error state of the buffer so that further processing of input can take place. This ensures that the input does not lead to an infinite loop of error message display. |
cin.ignore() | This function is used to ignore the rest of the line after the first instance of error that has occurred and it skips to or moves to the next line. |
cin.eof() | This function can be used to check end of file errors. This returns 1 if the program tried reading something but , it was from the end of the file. |
Here is a screenshot of the various wrong inputs given, and them being handled by the program till a correct input is provided.
Though this technique seems to work fine it hides a dangerous fault that can occur. This can be considered as a dis advantage of using c++. This technique does not catch certain types of input.
The following screenshots show 2 inputs that is accepted and the numerical part is printed.
So, how can this erroneous inputs be handled?
The technique we can apply is to accept the input as a string. The analyze the string to be of the illegal types shown above using regular expressions. If the input is valid then convert it into an integer and use it in the program else display an error message.
Though its possible, its very difficult to be achieved in c++. This is mainly because, c++ doesn’t support regular expressions by default, we have to make use of the regex library which is quite complex to use.
So to conclude, though C++ provides some handy tools to validate inputs, it does not help us to cover all possible situations in a straight forward way, which would lead us to use other workarounds to get our job done. But the validation of input can be handled in an efficient way with languages like java and c#.
Update 1: 29th Sept 2015
Blog Reader @Nick has provided a solution that is free from reg-ex, and i encourage you to try this out as well and let me know how it works in the comments:
A solution to the problem regex expression free
#include #include #include int main() { std::string line; int num; //split onto multiple lines for readability while((std::cout <> num) && !(is >> line)) //re-using `line` to test for extra stuff after the number { break; //done, we got what we wanted } std::cerr << "Invalid input, try again." << std::endl; } }
Reblogged this on Dinesh Ram Kali..
How to restrict user to enter fixed number in variable???example: If i want only 3 digits in int a. than user can not enter 4th digits and throw an error and system will be stopped.
In that case you could provide a condition restricting the values to be less that 999, and if the condition doesn’t satisfy, throw an error.
Another method would be to use regular expression to match and see of the entered number matches the format of 3 digits, for example the regular expression could be [0-9][0-9][0-9]
When working with user input, despite the sentiment of this blog entry, you really should strive to be robust. Fortunately, the c++11 regex header makes this much less painful than it’s been in the past.
#include
#include
#include
#include
…
const std::regex integerPattern_3digit(“(\+|-)?[[:d:]]{0,3}”);
std::string staging;
std::cin >> staging;
if (!(std::match(staging, integerPattern_3digit)) throw std::exception();
// conventional wisdom is throwing for user input error is a bad practice
Annoyingly, word press captures the header declarations as html.
The headers used are
string
iostream
regex
exception
I hadn’t known this, thanks for it. Will update my post with your suggestion soon.
Pingback:Validated user input in C++ #TC1017 #Mastery 27
A solution to the problem regex expression free
#include
#include
#include
int main()
{
std::string line;
int num;
//split onto multiple lines for readability
while((std::cout <> num) && !(is >> line)) //re-using `line` to test for extra stuff after the number
{
break; //done, we got what we wanted
}
std::cerr << "Invalid input, try again." << std::endl;
}
}
Thank you very much, will update the post with your answer.
I disagree with a few of the premises, but thank you for the article.
There are some reasons not to use regex, but in modern C++, I think it’s hard to argue that “complexity” is one of them for validating a 3-digit number.
@apmccartney’s implementation using regex and modern C++ is the one I would recommend to your readers. If modern C++ is not a possibility, Boost has a regex library compatible with C++98/03.
Also, the code you highlighted (from @Nick) does not compile. See here: http://ideone.com/rT5ZgL
My experience is that by the time you have built an airtight parser without using regex (including all the time for false positives where we think we’re done, only to find out down the road that we missed a scenario), we find we would have been much better off having bitten the bullet to learn regex.
That being said, regex can be computationally intensive and isn’t a one fit-solution for everything. But in this case, I do think it’s the right tool for the job.
Thank you very much for your input