C++ input validation - c++

I am beginning C++ programming, and have to do a lot of input validation. I have found this function that seems universally applicable, but am having trouble with one aspect; If I were to type -90, the program doesn't give an error. my question(s) are:
1. How can I add the circumstance that input cannot be <= 0?
2. Is there a better way to limit users input? Maybe a library within C++?
Thank you for any help, or advice.
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}

You can use functions to validate
template <typename T>
T getValidatedInput(function <bool(T)> validator) {
T tmp;
cin >> tmp;
if (!validator(tmp)) {
throw ios_base::failure("Invalid input.");
}
return tmp;
}
Usage
int input = getValidatedInput<int>([] (int arg) -> bool {
return arg >= 0;
});

std::istream::operator >> is defined in terms of strtol, strtoul, and cousins*, which unfortunately all invariably accept a minus sign even for unsigned types.
Essentially all you can do is accept signed int input and compare the result to zero. std::cin.setf( std::ios::failbit ) artificially raises a conversion exception, so you can sort-of emulate how the conversion function should behave on error, but that might not really be much help.
* operator >> is defined in terms of std::num_get, which is defined in terms of scanf, which is defined in terms of strto*. Everyone just passed the buck, but strtoul is pretty surely defective.

Use unsigned int as a template parameter.
Only you can setup a rules about what input is valid and what is not.

I hope this is what you're after, it exit's upon entering zero, but will display negative numbers. It throws an exception error due to the input catch method.
#include "stdafx.h"
#include <iostream>
using namespace std;
void inputcatch()
{
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
}
int main()
{
int input;
bool quit = false;
while (!quit)
{
cout << "Enter number" << endl;
cin >> input;
if (cin.fail())
{
inputcatch();
cout << "incorrect input" << endl;
}
else if (input == 0)
{
quit = true;
}
else
{
cout << "your number: " << input << endl;
}
}
return 0;
}

Related

Is there a way to have exceptions work indefinitely?

I have been trying to take an input from the user. I want to ensure that the input meets my requirements for the rest of the code for which I have used a try and catch block.
However, after only one time catching, it aborts the code. I want to ensure that after catching error it actually goes back to the input function for as many times until the user gives the program a valid input. Is there a way to do that except not using try catch blocks altogether?
Here's the code:
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
long num; // I need num as global
long get_input()
{
string input;
long number;
cout << "Enter a positive natural number: ";
cin >> input;
if ( !(stol(input)) ) // function for string to long conversion
throw 'R';
number = stol(input);
if (number <= 0)
throw 'I';
return number;
}
int main()
{
try
{
num = get_input();
}
catch (char)
{
cout << "Enter a POSTIVE NATURAL NUMBER!\n";
}
// I want that after catch block is executed, the user gets chances to input the correct number
// until they give the right input.
return 0;
}
You need explicitly write such a handling, e.g. via loop:
int main()
{
while (1) {
try
{
num = get_input();
return 0; // this one finishes the program
}
catch (char)
{
cout << "Enter a POSTIVE NATURAL NUMBER!\n";
}
}
}

C++ advice on exception handling

As I am very new to exceptions, I am having some trouble with the below memory exception code. Basically, I would need to calculate and show sum of 10 positive inputs. During the input, my program should use exception mechanism to display a message that it doesn't allow negative numbers / not-a-numbers (NaN) if so is the input and then exit the program. I am told to use std::cin.fail() to detect whether the value entered fits the variable type(but I am not sure how to implement it). Would appreciate your help thanks!
#include <iostream>
int main() {
int number;
int a=-2;
try {
for(int i=0; i<10;i++) {
std::cin>>number;
}
}
catch (...) {
number==-number?
std::cout << "Its negative"<<std::endl;
number==a?
std::cout << "Its NaN"<<std::endl;
}
}
You say "10 positive inputs", but you have int number;. If your number is going to be an integer, then it can't take fractions like 33.44 for instance, and it also can't be NaN (so you wouldn't need to check for that). If you want to allow fractions, do double number instead. That aside, the check could look like this:
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
After every inputted number, you do the std::cin.fail() check. If it failed, you can just return. In this example, I also made it print the invalid input. For that you need to call std::cin.clear(); to reset that error flag, and then you can put that invalid input into an std::string (which should work, unlike with the number). You need to include <string> for that. If you don't need to print anything, you can just return and forget about the clearing, the string and the output. Also, in this example, since the mess made by the invalid input is neatly cleaned up, you could take more (valid) inputs again if you don't return instead.
Next, checking for negative numbers:
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
Finally, the NaN check (for double):
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
You need to include <math.h> for the isnan.
Putting it all together, it could look like this:
#include <iostream>
#include <string> // std::istream >> std::string
#include <math.h> // isnan
int main() {
double number;
for (int i = 0; i < 10; i++) {
std::cin >> number;
if (std::cin.fail()) {
std::cin.clear();
std::string input;
std::cin >> input;
std::cout << "input failed! Invalid input: " << input << std::endl;
return -1;
}
if (number < 0) {
std::cout << "Error: Negative number!" << std::endl;
return -1;
}
if (isnan(number)) {
std::cout << "Error: number is NaN!" << std::endl;
return -1;
}
}
return 0;
}

How to throw an std::iostream failure in C++?

How do I manually throw an std::iostream::failure?
I have a try-catch loop that catches an exception when the user tries to input a non-integer string, however it does not throw an exception if the user tries to input a float since it will try to read everything before the decimal point in a float value. My solution is to manually throw the exception if there is still data remaining in the stream, how do I do that?
/*
Sample Implementation Code in C++
Handling Inputs from User in C++
This code only stops running when the user
inputs the appropriate values. Otherwise, the program
will continue asking the user for input.
*/
#include <iostream>
#include <limits> //numeric_limits
#include <stdexcept>
int main() {
std::cin.exceptions(std::ios::failbit); // set exceptions to be thrown when a failbit is set
int num = 0;
int den = 0;
while (true) {
try {
std::cout << "Enter numerator: ";
std::cin >> num;
if(std::cin.peek() != '\n') {
//HOW TO DO THIS PART?
std::iostream::failure e;
throw e;
}
std::cout << "Enter denominator: ";
std::cin >> den;
std::cout << "The quotient is " << num/den << std::endl;
} catch (std::iostream::failure& e){
std::cout << "Input should be an integer." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
return 0;
}
Apparently it's as simple as:
throw std::iostream::failure("");
the important thing I forgot is the empty string ("") since it has a constructor that takes a string argument but not a void argument.

Catching strings while using cin for integer input [duplicate]

This question already has answers here:
Good input validation loop using cin - C++
(4 answers)
Closed 9 years ago.
I've seen similar posts to this all around google/stackoverflow. However, I can't find one close enough to my scenario and I don't know C/C++ well enough to port other suggestions over to my methods. Perhaps that's a sign in and of itself...
Regardless, here is my code:
while (true)
{
print("\nSend message, enter command, or \"9\" for help.\n");
if (cin >> input)
{
if (input == TERMINAL_HELP)
{
//Some help code.
}
else if (input == TERMINAL_EXIT)
{
//Some exit code.
}
else if (input < 4 && input >= 0)
{
// Some processing code.
}
else
{
print("Please enter a valid message.");
}
}
else
{
print("Please enter a valid message.");
}
}
The catches works fine for single characters or integers outside of the range [0-4]. But when I put a string in, it gets very weird. It keeps looping through itself infinitely. However after the first time this should be impossible because I do not press enter. It continues through as if it is receiving a blank infinitely.
If you have any suggestions or can point me in the direction of fixing my issue I'd appreciate it! Thanks!
NOTE:
I was trying to follow this, and it worked to some extent. (I got the cin >> input within the if statement idea from this link...) But it does not work to block strings from making the program loop oddly.
Good input validation loop using cin - C++
Just to get you started with something..
Key points:
the iostreams (including cin) have something called "error flags"
when error occurs, the stream can be configured to either *) raise an exception *) skip next operations
the default configuration is .. to not throw and skip further operations
This means, that if you do:
cin >> integer1;
cin >> integer2; // *!
cin >> integer3; // !
cin >> integer4; // !
and if the user provides a non-integer at the line marked with (*), then at this point of time the cin will enter an error state and operations marked with (!) will be skipped.
Most probably this is why you get weird behavior like infinite read loops etc.
To handle this:
either configure the stream to throw exceptions - and catch them
or check error state after every few reads - and handle them
i.e.
cin >> integer1; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer2; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer3; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin >> integer4; if(cin.fail()) { cout << "wtf?!"; cin.clear(); .. return; }
cin.reset clears error flags and allows further operation on the stream. However, all the trash-data will still linger in the stream. So, there's no point in trying to read further. After cin.reset you should somehow remove that bad-data and recover from the situation. I've marked the places with "..", because there are many ways to do it.
For example, cin.ignore..
Now please refer to all-that-other posts :) I'm sure that you will now quickly find a solution
EDIT: aargh.. sorry, I've floated too far from the actual answer.. What you actually wanted is not a good-errorhandling, but something similar to what sehe wrote: instead of reading an integers, you should read a "string" and then inspect it, and then either re-parse them as integers or treat as string-data..
Here is a slightly fixed up minimal example (that compiles...) showing how you could do the stuff you try around
msg = input + '0';
Namely:
std::ostringstream oss;
oss << input;
auto msg = oss.str();
Or, using even more c++11 features (if your compiler has them):
auto msg = to_string(input);
The rest without further comments:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int const TERMINAL_EXIT = 9;
int const TERMINAL_HELP = 8;
static int devHandle = 0;
void print(char const*const msg) { cout << msg; }
void send(int, std::string const&) {} // TODO
void receive(int, std::string&) {} // TODO
void help_routine() {} // TODO
int main(int argc, const char *argv[])
{
while (true)
{
print("\nSend message, enter command, or \"9\" for help.\n");
// Read in message to send to DigiSpark.
long input;
if (cin >> input)
{
if (input == TERMINAL_HELP)
{
help_routine();
}
else if (input == TERMINAL_EXIT)
{
break;
}
else if (input < 4 && input >= 0)
{
#ifdef HAVE_CXX11
std::string msg = to_string(input);
#else
std::ostringstream oss;
oss << input;
std::string msg = oss.str();
#endif
// Send mimicking command line arguments.
send(devHandle, msg);
cout << "\nSent message: " << msg << endl;
print("Receiving message...\n");
receive(devHandle, msg);
while (!msg.empty())
{
receive(devHandle, msg);
}
cout << "Received message: " << msg << endl;
}
else
{
print("Please enter a valid message.");
}
}
else
{
print("Please enter a valid message.");
}
}
return 0;
}

How do I sanitise cin?

Say I have a program that takes in integers. How do I stop the program from falling apart if the user enters an out of range number, or a letter or something?
The cin's base class is std::basic_istream. The input stream indicates a recoverable error in case it cannot extract the requested data from the stream. In order to check for that error bit, std::basic_istream::fail() method must be used — it returns true if there was a failure or false if everything is alright. It is important to remember that if there is an error, the data is left in the stream and, of course, the error bit(s) must also be cleared using std::basic_istream::clear(). Also, a programmer must ignore incorrect data, or otherwise an attempt to read something else will fail again. For that purpose, std::basic_istream::ignore() method can be used. As for the valid range of values, it must be checked manually. Okay, enough theory, here is a simple example:
#include <limits>
#include <iostream>
int main()
{
int n = 0;
for (;;) {
std::cout << "Please enter a number from 1 to 10: " << std::flush;
std::cin >> n;
if (std::cin.fail()) {
std::cerr << "Sorry, I cannot read that. Please try again." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (n < 1 || n > 10) {
std::cerr << "Sorry, the number is out of range." << std::endl;
continue;
}
std::cout << "You have entered " << n << ". Thank you!" << std::endl;
break;
}
}
Hope it helps. Good Luck!
I prefer reading the input as strings, and then sanitizing them with boost::lexical_cast<>:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main () {
std::string s;
while( std::cin >> s) {
try {
int i = boost::lexical_cast<int>(s);
std::cout << "You entered: " << i << "\n";
} catch(const std::bad_cast&) {
std::cout << "Ignoring non-number: " << s << "\n";
}
}
}
Postscript: If you are allergic to Boost, you can use this implementation of lexical_cast:
template <class T, class U>
T lexical_cast(const U& u) {
T t;
std::stringstream s;
s << u;
s >> t;
if( !s )
throw std::bad_cast();
if( s.get() != std::stringstream::traits_type::eof() )
throw std::bad_cast();
return t;
}
something like this should do you need to clear the buffer after checking aswell if i remember right
if (cin.fail())
{
cout<<"need to put a number"<<endl;
cin.clear();
cin.ignore();
}
If You dont want to add libraries to your code you could also use do..while() statements.
in your do while you will ask for user input and then receive it to your variable then in the while part you will be able to check that this is the data you are expecting if not continue to ask for the data.
just another option ....even though the answer already mentioned should work more than adequately
You can use the following code for simplest and fast checking of valid input in int :
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int intb;
while( !( cin>>intb ) ){
cin.clear ();
cin.ignore (1000, '\n');
cout<<"Invalid input enter again: "<<endl;
}
cout<<"The value of integer entered is "<<b<<endl;
return 0;
}
The while loop keeps on iterating until it gets the right input.
cin.clear() changes the error control state.
cin.ignore() removes clear the input stream so that new input can be taken again. If not done thw while loop will be in infinite state.