0

Currently having issues creating an integer validation loop in my code.

Trying to validate for an integer, however this code fails to work if you input, for example the string '22a' it sets trial_no as 22. Is there any way to check that every charachter input is indeed a string, such that '22a' or '2a2' would be considered erroneous and the loop would continue until a valid integer was input?

int trial_no;

bool valid = false;

while(!valid) 
{
    valid = true; //assume trial_no will be an integer
    cout << "Enter the number of die throws to simulate" << endl;
    cin >> trial_no;

    if(cin.fail()) // exit loop condition is dependent on trail_no being a valid integer
    {
        cin.clear(); //corrects stream
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); //skips left over stream data (numeric_limit
        // is in case user enters more than one letter))
        cout << "Please enter an integer value" << endl;
        valid = false; //cin not an integer so loop goes round to try again
    }
}
  • 3
    Read it in as a std::string and then convert it to an integer. If the conversion fails, it's not an integer. – Anon Mail Oct 23 '17 at 14:24
  • Possible duplicate of [How do I check if a C++ string is an int?](https://stackoverflow.com/questions/2844817/how-do-i-check-if-a-c-string-is-an-int) – user2891462 Oct 23 '17 at 14:25

1 Answers1

1

Arguably the best way is to read the entire line as a string and utilize the std::stoi function:

#include <iostream>
#include <string>
int main() {
    std::cout << "Enter an integer: ";
    std::string tempstr;
    bool valid = false;
    std::getline(std::cin, tempstr);
    try {
        int result = std::stoi(tempstr);
        std::cout << "The result is: " << result;
        valid = true;
    }
    catch (std::invalid_argument) {
        std::cout << "Could not convert to integer.";
        valid = false;
    }
}

As pointed out in the comments, this function can also throw a std::out_of_range exception. This assumes your compiler is C++11 (+) capable. If not, go down the std::stringstream route:

std::string tempstr;
std::getline(std::cin, tempstr);
std::stringstream ss(tempstr);
int result;
bool valid = false;
if (ss >> result) {
    valid = true;
}
else {
    valid = false;
}
Ron
  • 14,674
  • 4
  • 34
  • 47
  • 1
    Please note that `std::stoi` could throw a `std::out_of_range` exception too. Besides, it may be useful to retrieve the number of characters processed and to pass the base. – Bob__ Oct 23 '17 at 14:37
  • This actually doesn't answer the question since stoi's output of "22a" is still 22. – xyious Oct 23 '17 at 15:39
  • @xyious The answer is a receipt and a nudge in the right direction. Getting into input stream and std::cin internals is often not the way to go. – Ron Oct 23 '17 at 16:16
  • But it seems the std::cin methods shown in other questions and this answer with stoi both don't chop off the unwanted alphabet characters for integer input. – The_Redhawk Feb 24 '21 at 05:24