I'm having trouble making input validation for numeric input only. Below is my code it loops every time I input a letter, inputting the wrong number doesn't though. It loops "Invalid Input, please try again." and the only option is to close it. How can i fix this?
while (!(cin >> userOption) || userOption < 1 || userOption > 12) {
cout << "Invalid Input, please try again." << endl;
cin >> userOption;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
You don't want cin >> userOption both in the while condition and inside the loop, as that makes two inputs per loop.
The one in the while condition should be enough.
First of all initialize userOption:
unsigned int userOption = 0;
Then go like this:
while ( userOption < 1 || userOption > 12 /* or even true, like Atle suggested */)
{
cin >> userOption;
if( !cin || userOption < 1 || userOption > 12 )
{
cout << "Invalid Input, please try again." << endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
continue;
}
else
break; //this is looping when letter inputed
}
Try this to break out of the loop if result is OK:
while (true) {
if (!(cin >> userOption) || (userOption_tmp < 1) || (userOption_tmp > 12)) {
cout << "Invalid Input, please try again." << endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
}
else {
break;
}
//this is looping when letter inputed
}
Related
I found this similar question being asked so many times but I still couldn't find a solution for mine.
In my case, I want to display something when the user enters a number from 1 - 5, give an error when he inputs something wrong like characters, "3g", "3.", "b3" and any float number.
I tried the code below, but it created so many other problems. Like if I enter 3g or 3.5, it'll only take the 3 and ignore the rest so the (!cin) doesn't work at all.
Second, if I input something like a character, the __userChoice will be automatically converted into 0 and the program prints out "Please select a number from 1 to 5." instead of "Invalid input, please input an integer number.\n", which is what I want.
cout << "Please select: ";
cin >> __userChoice;
if (__userChoice > 0 && __userChoice < 5) {
cout << "You select menu item " << __userChoice <<". Processing... Done!\n";
}
else if (__userChoice == 5) {
Finalization(); //call exit
}
else if (__userChoice <= 0 || __userChoice > 5) {
cout << "Please select a number from 1 to 5.\n";
}
else (!cin) {
cout << "Invalid input, please input an integer number.\n";
}
cin.clear();
cin.ignore(10000, '\n');
operator>> is not guaranteed to output a meaningful integer value if a failure occurs, but you are not checking for failure before evaluating __userChoice, and the way your ifs are structured the else (!cin) check will never be reached. But even if operator>> is successful, you are not checking if the user entered more than just an integer.
To do what you are asking for, you should read from std::cin into a std::string first using std::getline(), and then use std::istringstream or std:stoi() (or equivilent) to convert the string to an int with error checking.
For example:
bool strToInt(const std::string &s, int &value)
{
std::istringstream iss(s);
return (iss >> value) && iss.eof();
// Or:
std::size_t pos;
try {
value = std::stoi(input, &pos);
}
catch (const std::exception &) {
return false;
}
return (pos == input.size());
}
...
std::string input;
int userChoice;
std::cout << "Please select: ";
std::getline(std::cin, input);
if (strToInt(input, userChoice))
{
if (userChoice > 0 && userChoice < 5)
{
std::cout << "You selected menu item " << userChoice <<". Processing... Done!\n";
}
else if (userChoice == 5)
{
Finalization(); //call exit
}
else
{
std::cout << "Please select a number from 1 to 5.\n";
}
}
else
{
std::cout << "Invalid input, please input an integer number.\n";
}
This question already has answers here:
Checking cin input stream produces an integer
(8 answers)
Closed 4 years ago.
I want to obtain an input from the user and validate it as an integer, however my method seems to fail, when a letter or word the program just ends. Any one have a quick and easy fix for this?
int getUserInput(){
int maxNumber;
// the user input a valid integer, process it
if (cin >> maxNumber)
{
if (maxNumber>1 || maxNumber<=100) {
return maxNumber;
}
} else{
getUserInput();
}
}
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;
}
You didn't state what range you wanted the input to be in so adjust accordingly.
int getUserInput() {
int maxNumber;
while (!(cin >> maxNumber) || maxNumber <= 1 || 100 < maxNumber) {
if (cin)
cout << "number out of range, try again: ";
else {
cin.clear();
cin.ignore(numeric_limits<int>::max(), '\n');
cout << "Not a number, please try again : ";
}
}
return maxNumber;
}
I wanted the user to input 1, 2, 3, or 4, and ONLY those numbers.
I do not want: 5, 79, 4rf, 1XXXXX, 2!, abc 1234, etc.
If I use 'cin >> ', then it would cut off the input to something like '2!' to the 2 and leave the '!' in for the next input, so getline() is preferable. The code I have listed technically works, but leaves an extra line of input when I ask again for another input after the user put in a invalid one.
Thank you for the help.
bool check = true;
string input;
int choice;
cout << "Please enter 1, 2, 3, or 4:" << endl;
getline(cin, input);
do
{
check = true;
if (input.length() != 1 || !isdigit(input[0]))
{
cout << "error, enter a valid input" << endl;
check = false;
cin.clear();
cin.ignore(INT_MAX, '\n');
getline(cin, input);
}
else
{
choice = stoi(input);
if (!(choice == 1 || choice == 2 || choice == 3 || choice == 4))
{
cout << "error, enter a valid input" << endl;
check = false;
cin.clear();
cin.ignore(INT_MAX, '\n');
getline(cin, input);
}
else
{
check = true;
}
}
} while (check == false);
getline(cin, input); consumes an entire line or fails, and failure for getline on cin is pretty much the end of cin. If you got data at all, you got the whole line. There is nothing for cin.ignore(INT_MAX, '\n'); to ignore, so the user winds up having to hit enter again before they can get to the getline(cin, input); retry.
Keeping your basic stricture, I'd clean it up to something more like
bool check = false; // assume failure
string input;
int choice;
cout << "Please enter 1, 2, 3, or 4:" << endl;
while (!check)
{
if (getline(cin, input)) // test that we got something
{
if (input.length() != 1 || !isdigit(input[0]))
{
cout << "error, enter a valid input" << endl;
// don't need to do anything else here
}
else
{
choice = input[0] - '0'; // easier conversion
if (!(choice == 1 || choice == 2 || choice == 3 || choice == 4))
{
cout << "error, enter a valid input" << endl;
// don't need to do anything else here
}
else
{
check = true; // all done
}
}
}
else
{
// to be honest there isn't much you can do here. You can clear and
// ignore, but it's hard to make unformatted input fail and still
// have a viable console. Maybe you should throw an exception, but
// for a simple program I'm all for giving up.
cerr << "Aaaaaaahhhhrrrg!\n";
exit(-1);
}
}
I'm assuming failure because I only have one place I need to set the check flag: On success! This makes it a bit easier to pick this code up and put it in a function so you can reuse it more easily. Make the loop go forever and replace check = true; with return choice;.
Alright so I got a simple code here:
(Enter number between 0-100 if cin is not a varable then clear cin, ignore the error line)
void Numbrs(int v1)
{
do
{
cout << "Please enter a number between 0 and 100" << endl;
cin >> v1;
if (!(cin >> v1))
{
cout << "Invalid input, please try again." << endl;
cin.clear();
cin.ignore (numeric_limits<streamsize>::max(), '\n');
}
else
{
if (v1 < 0 || v1 > 100)
{
cout << "Invalid number, please try again." << endl;
}
else
{
}
}
} while (v1 < 0 || v1 > 100);
}
(Of course its not doing anything now, because I'm going crazy its not working)
My problem with this is when I enter ANY number it always ignores the first one, here's an example:
Please enter a number between 0 and 100
111
315
Invalid number, please try again.
Please enter a number between 0 and 100
50
40
Could anybody explain why is this happening? It happens to me almost every time when I try to use cin.clear() and cin.ignore (numeric_limits<streamsize>::max(), '\n').
Note that you are repeating the input operation:
cin >> v1; // Try removing this line
if (!(cin >> v1)) {
...
}
I am trying to make a cin where the user can only enter 0 to 1. If the user doesnt enter those numbers then he should get an error saying "Please enter within the range of 0 to 1."
But its not working.
What am i doing wrong?
int alphaval = -1;
do
{
std::cout << "Enter Alpha between [0, 1]: ";
while (!(std::cin >> alphaval)) // while the input is invalid
{
std::cin.clear(); // clear the fail bit
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore the invalid entry
std::cout << "Invalid Entry! Please Enter a valid value: ";
}
}
while (0 > alphaval || 1 < alphaval);
Alpha = alphaval;
Try this:
int alphaval;
cout << "Enter a number between 0 and 1: ";
cin >> alphaval;
while (alphaval < 0 || alphaval > 1)
{
cout << "Invalid entry! Please enter a valid value: ";
cin >> alphaval;
}
If you want to trap empty lines I'd use std::getline and then parse the string to see if the input is valid.
Something like this:
#include <iostream>
#include <sstream>
#include <string>
int main()
{
int alphaval = -1;
for(;;)
{
std::cout << "Enter Alpha between [0, 1]: ";
std::string line;
std::getline(std::cin, line);
if(!line.empty())
{
std::stringstream s(line);
//If an int was parsed, the stream is now empty, and it fits the range break out of the loop.
if(s >> alphaval && s.eof() && (alphaval >= 0 && alphaval <= 1))
{
break;
}
}
std::cout << "Invalid Entry!\n";
}
std::cout << "Alpha = " << alphaval << "\n";
return 0;
}
If you want a different prompt on error then I'd put the initial prompt outside the loop and change the inner prompt to what you prefer.
Week one of C++, starting with Peggy Fisher's Learning C++ on Lynda.com.
This is what I came up with. Love to receive feedback.
int GetIntFromRange(int lower, int upper){
//variable that we'll assign input to
int input;
//clear any previous inputs so that we don't take anything from previous lines
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
//First error catch. If it's not an integer, don't even let it get to bounds control
while(!(cin>>input)) {
cout << "Wrong Input Type. Please try again.\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
//Bounds control
while(input < lower || input > upper) {
cout << "Out of Range. Re-enter option: ";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
//Second error catch. If out of range integer was entered, and then a non-integer this second one shall catch it
while(!(cin>>input)) {
cout << "Wrong Input Type. Please try again.\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
//return the cin input
return input;
}
As the exercise was to order Hamburgers, this is how I ask for the amount:
int main(){
amount=GetIntFromRange(0,20);
}