17

I was typing this and it asks the user to input two integers which will then become variables. From there it will carry out simple operations.

How do I get the computer to check if what is entered is an integer or not? And if not, ask the user to type an integer in. For example: if someone inputs "a" instead of 2, then it will tell them to reenter a number.

Thanks

 #include <iostream>
using namespace std;

int main ()
{

    int firstvariable;
    int secondvariable;
    float float1;
    float float2;

    cout << "Please enter two integers and then press Enter:" << endl;
    cin >> firstvariable;
    cin >> secondvariable;

    cout << "Time for some simple mathematical operations:\n" << endl;

    cout << "The sum:\n " << firstvariable << "+" << secondvariable 
        <<"="<< firstvariable + secondvariable << "\n " << endl;

}
jww
  • 97,681
  • 90
  • 411
  • 885
user2766546
  • 185
  • 1
  • 1
  • 7

8 Answers8

41

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;
}
Chemistpp
  • 2,006
  • 2
  • 28
  • 48
  • @crush cin does not interpret the input as a char, it parses it, but "a" can't be parsed as an integer. Nor can anything else, but an integer. – brunocodutra Sep 10 '13 at 21:14
  • Check it man. Compile the code with a message. If you enter 'a' it will throw the fail bit – Chemistpp Sep 10 '13 at 21:14
  • Seems I've been away from C++ for too long. – crush Sep 10 '13 at 21:17
  • 4
    `if(!cin)` is valid, but it hides what it is actually doing. `if (cin.fail())` does the same thing and is more clear. – Zac Howland Sep 10 '13 at 21:19
  • 1
    It should be noted that if the input were something like 10abc then cin.fail will return false. The 10 would get parsed as an int and the abc portion will remain in the stream waiting to be read. – natet Sep 28 '17 at 23:46
3

Heh, this is an old question that could use a better answer.

User input should be obtained as a string and then attempt-converted to the data type you desire. Conveniently, this also allows you to answer questions like “what type of data is my input?”

Here is a function I use a lot. Other options exist, such as in Boost, but the basic premise is the same: attempt to perform the string→type conversion and observe the success or failure:

template <typename T>
auto string_to( const std::string & s )
{
  T value;
  std::istringstream ss( s );
  return ((ss >> value) and (ss >> std::ws).eof())  // attempt the conversion
    ? value                                         // success
    : std::optional<T> { };                         // failure
}

Using the optional type is just one way. You could also throw an exception or return a default value on failure. Whatever works for your situation.

Here is an example of using it:

int n;
std::cout << "n? ";
{
  std::string s;
  getline( std::cin, s );
  auto x = string_to <int> ( s );
  if (!x) return complain();
  n = *x;
}
std::cout << "Multiply that by seven to get " << (7 * n) << ".\n";

limitations and type identification

In order for this to work, of course, there must exist a method to unambiguously extract your data type from a stream. This is the natural order of things in C++ — that is, business as usual. So no surprises here.

The next caveat is that some types subsume others. For example, if you are trying to distinguish between int and double, check for int first, since anything that converts to an int is also a double.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
1

There is a function in c called isdigit(). That will suit you just fine. Example:

int var1 = 'h';
int var2 = '2';

if( isdigit(var1) )
{
   printf("var1 = |%c| is a digit\n", var1 );
}
else
{
   printf("var1 = |%c| is not a digit\n", var1 );
}
if( isdigit(var2) )
{
  printf("var2 = |%c| is a digit\n", var2 );
}
else
{
   printf("var2 = |%c| is not a digit\n", var2 );
}

From here

nook
  • 2,378
  • 5
  • 34
  • 54
  • so change to characters instead of integers at the variable assignments, then use the rest of the code as is? (and upvoted because the answer is still very usable after this slight tweak) – user2366842 Sep 10 '13 at 21:15
  • Because istream will fail at inserting into an integer if you supply a character, so your variable will have whatever data in it that was there before. – Zac Howland Sep 10 '13 at 21:15
  • 2
    @crush the OP wants to check wheter the input is an **integral value** not a **digit**. – brunocodutra Sep 10 '13 at 21:18
  • @brunocodutra : Was going to post the same thing – boxed__l Sep 10 '13 at 21:19
  • "`isdigit` is used to check if the **first character** in `str` is a digit and therefore a valid candidate to be converted by `atoi` into an integer value." – jpenna Feb 05 '18 at 01:59
1

If istream fails to insert, it will set the fail bit.

int i = 0;
std::cin >> i; // type a and press enter
if (std::cin.fail())
{
    std::cout << "I failed, try again ..." << std::endl
    std::cin.clear(); // reset the failed state
}

You can set this up in a do-while loop to get the correct type (int in this case) propertly inserted.

For more information: http://augustcouncil.com/~tgibson/tutorial/iotips.html#directly

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

You can use the variables name itself to check if a value is an integer. for example:

#include <iostream>
using namespace std;

int main (){

int firstvariable;
int secondvariable;
float float1;
float float2;

cout << "Please enter two integers and then press Enter:" << endl;
cin >> firstvariable;
cin >> secondvariable;

if(firstvariable && secondvariable){
    cout << "Time for some simple mathematical operations:\n" << endl;

    cout << "The sum:\n " << firstvariable << "+" << secondvariable 
    <<"="<< firstvariable + secondvariable << "\n " << endl;
}else{
    cout << "\n[ERROR\tINVALID INPUT]\n"; 
    return 1; 
} 
return 0;    
}
0

I prefer to use <limits> to check for an int until it is passed.

#include <iostream>
#include <limits> //std::numeric_limits

using std::cout, std::endl, std::cin;

int main() {
    int num;
    while(!(cin >> num)){  //check the Input format for integer the right way
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        cout << "Invalid input.  Reenter the number: ";
      };

    cout << "output= " << num << endl;

    return 0;
}
Ingo Mi
  • 999
  • 12
  • 26
0

Under C++11 and later, I have the found the std::stoi function very useful for this task. stoi throws an invalid_argument exception if conversion cannot be performed. This can be caught and handled as shown in the demo function 'getIntegerValue' below.

The stoi function has a second parameter 'idx' that indicates the position of the first character in the string after the number. We can use the value in idx to check against the string length and ascertain if there are any characters in the input other than the number. This helps eliminate input like 10abc or a decimal value.

The only case where this approach fails is when there is trailing white space after the number in the input, that is, the user enters a lot of spaces after inputting the number. To handle such a case, you could rtrim the input string as described in this post.

#include <iostream>
#include <string>

bool getIntegerValue(int &value);

int main(){
    
    int value{};
    bool valid{};

    while(!valid){
        std::cout << "Enter integer value: ";
        valid = getIntegerValue(value);
        if (!valid)
            std::cout << "Invalid integer value! Please try again.\n" << std::endl;
    }
    
    std::cout << "You entered: " << value << std::endl;

    return 0;
}

// Returns true if integer is read from standard input
bool getIntegerValue(int &value){
    bool isInputValid{};
    int valueFromString{};
    size_t index{};
    
    std::string userInput;
    std::getline(std::cin, userInput);

    try {
        //stoi throws an invalid_argument exception if userInput cannot be
        //converted to an integer.
        valueFromString = std::stoi(userInput, &index);

        //index being different than length of string implies additional
        //characters in input that could not be converted to an integer.
        //This is to handle inputs like 10str or decimal values like 10.12
        if(index == userInput.length()) isInputValid = true;
    }
    catch (const std::invalid_argument &arg) {
        ;       //you could show an invalid argument message here.
    }

    if (isInputValid) value = valueFromString;

    return isInputValid;
}
Chirag
  • 11
  • 3
-5

You could use :

int a = 12;
if (a>0 || a<0){
cout << "Your text"<<endl;
}

I'm pretty sure it works.