Checking Cin Input Stream Produces an Integer

Checking cin input stream produces an integer

You can check like this:

int x;
cin >> x;

if (cin.fail()) {
//Not an int.
}

Furthermore, you can continue to get input until you get an int via:

#include <iostream>



int main() {

int x;
std::cin >> x;
while(std::cin.fail()) {
std::cout << "Error" << std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin >> x;
}
std::cout << x << std::endl;

return 0;
}

EDIT: To address the comment below regarding input like 10abc, one could modify the loop to accept a string as an input. Then check the string for any character not a number and handle that situation accordingly. One needs not clear/ignore the input stream in that situation. Verifying the string is just numbers, convert the string back to an integer. I mean, this was just off the cuff. There might be a better way. This won't work if you're accepting floats/doubles (would have to add '.' in the search string).

#include <iostream>
#include <string>

int main() {

std::string theInput;
int inputAsInt;

std::getline(std::cin, theInput);

while(std::cin.fail() || std::cin.eof() || theInput.find_first_not_of("0123456789") != std::string::npos) {

std::cout << "Error" << std::endl;

if( theInput.find_first_not_of("0123456789") == std::string::npos) {
std::cin.clear();
std::cin.ignore(256,'\n');
}

std::getline(std::cin, theInput);
}

std::string::size_type st;
inputAsInt = std::stoi(theInput,&st);
std::cout << inputAsInt << std::endl;
return 0;
}

My code fails to verify input as an integer

If the user does not type in an integer, your code enters an infinite recursive loop that it does not recover from, eventually overflowing the call stack.

Try something more like this instead:

int getUserInput()
{
int number;

cout << "Enter a number between 1 - 100: ";

do
{
// if the user input a valid integer, process it

if (cin >> number)
{
if (number >= 1 && number <= 100)
break;

cout << "Number out of range, try again: ";
}
else
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');

cout << "Invalid input, try again: ";
}
}
while (true);

return number;
}

Checking input is an integer

If you need to check for a positive integer, you probably need
to convert the text to an integer as well. You should do both
at once; something along the lines of:

std::string line;
if ( !std::getline( std::cin, line ) ) {
// no input available...
} else {
std::istringstream parser( line );
int userNumber;
if ( parser >> userNumber >> std::ws
&& parser.get() == EOF
&& userNumber > 0 ) {
// All OK...
} else {
// Some error in the input.
}
}

It's also possible to use strtol, if you have the string from
elsewhere. Error detection is a bit tricky, because strtol
has some strange semantics in some cases:

int
getPositiveInteger( std::string const& input )
{
char const* end;
errno = 0;
long results = strtol( input.c_str(), &end, 10 );
if ( end != input.c_str() ) {
while ( isspace( static_cast<unsigned char>( *end) ) ) {
++ end;
}
}
return (errno == 0
&& end != input.c_str()
&& *end == '\0'
&& results > 0
&& results <= INT_MAX)
? results
: -1;
}

(I've returned -1 in case of an error.)

You'll notice the number of conditions you have to test to be
sure that stdtol has worked correctly.

Input data type check in loop not working as intended (C++)

Your main problem is that you only clear the error condition but never flush the offending input, so the input stream stays at the erroneous characters. The common way is to read (and discard) a full line for a failed conversion:

while (true) {
std::cout << ">>> ";
std::cin >> input;
std::cout << std::flush;

if (std::cin.eof()) { // do not try to read past an eof!
input = 0;
break;
}
if (std::cin.fail() || input < 0) {
std::string line;
std::cin.clear(); // reset the fail flag
std::getline(std::cin, line); // read until end of line
std::cout << "Failed";
continue;
}

break;
}

try and except, but in c++

An exception is a problem that arises during the execution of a program. Allowing the user to stop giving more input is not a problem. Your logic should handle. There are multiple ways to do it.

Try..catch is always there for you.

One way could be parsing the input to check if the input is an int. If not, break the while.

Another way could be as shown below.

#include <iostream>
using namespace std;
int main() {
int num;
cin >> num;
while(cin.fail()){
//your logic goes here
cin.clear();
cin.ignore(numeric_limits<int>::max(), '\n');
cin >> num;
};
return 0;
}

input stream in C++. A little confusion with cin unget() function

Lets take a closer look at skip_to_int

 if (cin.fail()) {

if the last input was bad

       cin.clear();

clear the flags and look for the next good data

       for (char ch; cin>>ch; ) {

get a character

            if (isdigit(ch) || ch=="-") {

if character is a character we want

                 cin.unget();

put it back into the stream

                 return;

exit the function!!!

            }

otherwise loop back around to get the next character

        }

no more characters, exit the loop

  }

error("no input");

Immediately following the unget, the function returns, ending the loop along with the function.

Checking for legitimate integer input in c++

Assuming that you can't use boost::lexical_cast, you can write your own version:

#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
template <class T1, class T2>
T1 lexical_cast(const T2& t2)
{
std::stringstream s;
s << t2;
T1 t1;
if(s >> std::noskipws >> t1 && s.eof()) {
// it worked, return result
return t1;
} else {
// It failed, do something else:
// maybe throw an exception:
throw std::runtime_error("bad conversion");
// maybe return zero:
return T1();
// maybe do something drastic:
exit(1);
}
}



int main() {
std::string smin, smax;
int imin, imax;

while(std::cout << "Enter min and max: " && std::cin >> smin >> smax) {
try {
imin = lexical_cast<int>(smin);
imax = lexical_cast<int>(smax);
break;
} catch(std::runtime_error&) {
std::cout << "Try again: ";
continue;
}
}

if(std::cin) {
std::cout << "Thanks!\n";
} else {
std::cout << "Sorry. Goodbye\n";
exit(1);
}
}


Related Topics



Leave a reply



Submit