Reputation: 1427
I am trying to allow only integrers to be inputted
Should Reject:
Should Accept:
Current Code
int getIntInput() {
int userInput;
while (true) {
std::cout << "> ";
std::cin >> userInput;
std::cout << std::flush;
if (std::cin.fail()) {
std::string cinBuffer;
std::cin.clear();
std::getline(std::cin, cinBuffer);
continue;
}
break;
}
return userInput;
}
Updated Code
Issues:
Accepts all rejections excluding "htr" (No numerals)
int getIntInput() {
std::string rawInput;
int parsedinput;
while (true) {
std::cout << "> ";
std::getline(std::cin, rawInput);
std::cout << std::flush;
try {
parsedinput = std::stoi(rawInput);
} catch (std::invalid_argument & e) {
continue;
} catch (std::out_of_range & e) {
continue;
}
break;
}
return parsedinput;
}
Finished Code
Accepts only integers with an optional parameter which will allow negative numbers to be accepted or rejected.
int getIntInput(bool allowNegatives = true) {
bool validIntInput;
std::string rawInput;
int parsedinput;
while (true) {
validIntInput = true;
// Grabs the entire input line
std::cout << "> ";
std::getline(std::cin, rawInput);
std::cout << std::flush;
for (int i = 0; i < rawInput.length(); i++) {
// Checks to see if all digits are a number as well as to see if the number is a negative number
if (!isdigit(rawInput[i]) && !(allowNegatives && i == 0 && rawInput[i] == '-')) {
validIntInput = false;
break;
}
}
if (!validIntInput) {
continue;
} else {
try {
// Try parse the string to an int
parsedinput = std::stoi(rawInput);
// Catch all possible exceptions, another input will be required
} catch (...) {
continue;
}
// If the code reaches here then the string has been parsed to an int
break;
}
}
return parsedinput;}
Upvotes: 2
Views: 154
Reputation: 37607
template<class T>
T findInStreamLineWith(std::istream &input) {
std::string line;
while (std::getline(input, line)) {
std::istringstream stream(line);
T x;
if (stream >> x >> std::ws && stream.eof()) {
return x;
}
// reenter value
// cout << "Enter value again: ";
}
throw std::invalid_argument("can't find value in stream");
}
…
auto x = findInStreamLineWith<int>(std::cin);
Upvotes: 0
Reputation: 41
If you don't mind the overhead, I would grab the input from cin with cin.getline()
and save it into a string. Then loop through the string and call isdigit
on each char. You can discard the chars that aren't digits by useing the str.erase
function.
You will need to #include cctype for isdigit()
.
Note: this will have at least O(N) runtime based on the length of your string.
Upvotes: 2
Reputation: 182
The way cin works when having to read an int, is that it starts parsing the integer and stops when it finds a non-int character, storing the parsed int in the variable. That's why on float numbers it stops on the dot and in input '5g' it will stop on g.
What you can do instead if you only want integer input, is to read the whole line and then check if every character in your string is numeric, with the following piece of code:
bool onlyNums = true;
for (int i=0;i<rawInput.size();i++) {
if (!isdigit(rawInput[i]))
onlyNums = false;
}
if (!onlyNums)
continue;
(You have to include ctype.h library for the above code)
Upvotes: 2