34

I want to create a program that takes in integer input from the user and then terminates when the user doesn't enter anything at all (ie, just presses enter). However, I'm having trouble validating the input (making sure that the user is inputting integers, not strings. atoi() won't work, since the integer inputs can be more than one digit.

What is the best way of validating this input? I tried something like the following, but I'm not sure how to complete it:

char input

while( cin>>input != '\n')
{
     //some way to check if input is a valid number
     while(!inputIsNumeric)
     {
         cin>>input;
     }
}
3
  • 1
    input is a pointer. Why are you taking input to it using cin ? I am not sure whether an address can be given that way but address locations are represented in hexa-decimal system and there chances of being alpha-numeric. Commented Apr 13, 2011 at 20:25
  • Gah, I was recreating this code from memory (not copying and pasting). Let me try and fix that. Commented Apr 13, 2011 at 20:26
  • your while condition won't compile. Perhaps you should go with for(cin>>input; input != '\n'; cin >>input) Commented Apr 13, 2011 at 20:45

8 Answers 8

55

When cin gets input it can't use, it sets failbit:

int n;
cin >> n;
if(!cin) // or if(cin.fail())
{
    // user didn't input a number
    cin.clear(); // reset failbit
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    // next, request user reinput
}

When cin's failbit is set, use cin.clear() to reset the state of the stream, then cin.ignore() to expunge the remaining input, and then request that the user re-input. The stream will misbehave so long as the failure state is set and the stream contains bad input.

Sign up to request clarification or add additional context in comments.

7 Comments

The problem with that (against my reading of the Q) is that it doesn't give up after one press of <ENTER>; rather - cin >> n will keep running until success, error or end-of-file.
@Tony: This is true, but it also doesn't advance the read pointer until it has a successful read. I've edited my post.
Don't forget to .reset() the stream.
Oddly this does not work on G++-47 compiler (Mint 16). No idea why.
@AlvinCaseria: Could you clarify what you mean by "does not work"?
|
23

Check out std::isdigit() function.

Comments

8

The problem with the usage of

cin>>number_variable;

is that when you input 123abc value, it will pass and your variable will contain 123.

You can use regex, something like this

double inputNumber()
{
    string str;
    regex regex_pattern("-?[0-9]+.?[0-9]+");
    do
    {
        cout << "Input a positive number: ";
        cin >> str;
    }while(!regex_match(str,regex_pattern));

    return stod(str);
}

Or you can change the regex_pattern to validate anything that you would like.

1 Comment

this is great idea in c++ 11
3

I find myself using boost::lexical_cast for this sort of thing all the time these days. Example:

std::string input;
std::getline(std::cin,input);
int input_value;
try {
  input_value=boost::lexical_cast<int>(input));
} catch(boost::bad_lexical_cast &) {
  // Deal with bad input here
}

The pattern works just as well for your own classes too, provided they meet some simple requirements (streamability in the necessary direction, and default and copy constructors).

Comments

2

Why not just using scanf("%i") and check its return?

Comments

1

If you already have the string, you can use this function:

bool isNumber( const string& s )
{
  bool hitDecimal=0;
  for( char c : s )
  {
    if( c=='.' && !hitDecimal ) // 2 '.' in string mean invalid
      hitDecimal=1; // first hit here, we forgive and skip
    else if( !isdigit( c ) ) 
      return 0 ; // not ., not 
  }
  return 1 ;
}

Comments

0

I guess ctype.h is the header file that you need to look at. it has numerous functions for handling digits as well as characters. isdigit or iswdigit is something that will help you in this case.

Here is a reference: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/isdigit_xml.html

Comments

0

Something that can be done is read text input and then try to convert that to a number:

try 
{
    std::string str;
    std::getline(std::cin, str)
    age = std::stoi(str)
}
catch(...)
{
    // ...
}

Then you can handle the errors by catching the exceptions.

https://en.cppreference.com/w/cpp/string/basic_string/stol

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.