while loop - nothing happens after first input - c++

int option;
int invalidOption2 = 0;
while(invalidOption2 == 0){
try{
cin>>option;
if(!cin){
error("invalid input");
}
if(option<1 || option>2){
error("invalid input");
}
if(option==1) {
invalidOption2 = 1;
cout<<"option 1 was selected"<<endl;
}
else if(option==2) {
invalidOption2 = 1;
cout<<"option 2 was selected"<<endl;
}
}
catch(runtime_error& e) {
cerr <<"Please enter a valid option" << endl;
}
}
When using the above code, for the first value I input it will move on to the next line and wait for another input, instead of displaying either the option messages or the error message. However when I enter a second value it works as normal.
for example if I entered
a (nothing happens here, so I need to enter another value)
1
"you have selected option 1"
would be displayed and no error message for the original invalid input.
I would like to know how to get the result below instead.
a
"Please select a valid option"
1
"you have selected option 1"
any help would be appreciated

You won't get to the "Please enter a valid option" unless an
exception is thrown. You don't show error, but if it doesn't
throw an exception, you'll never get to the catch block.
Also, cin >> option almost certainly leaves a new line in the
buffer, which may cause later problems, and whien you enter an
alpha, if option is type int, cin will enter an error
state, which needs to be cleared (and the erronous input
removed). So in the error case (!cin), you need to call
cin.clear(), and in all cases, you probably want to call
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n'
).
An alternative solution, which avoids most of these problems, is
to read complete lines (using std::getline( std::cin, line )),
and then use std::istringstream to parse the line. This will
leave std::cin in a good state, and ready to input the next
line.

Option is likely of integer type, so cin can't read 'a' into it, so it is ignored.
Is this your case?
You could modify it like this:
char option;
while(invalidOption2 == 0){
try{
cin>>option;
if(!cin){
error("invalid input");
}
if(option<'1' || option>'2'){
error("invalid input");
}
if(option=='1') {
invalidOption2 = 1;
cout<<"option 1 was selected"<<endl;
}
else if(option=='2') {
invalidOption2 = 1;
cout<<"option 2 was selected"<<endl;
}
}
catch(runtime_error& e) {
cerr <<"Please enter a valid option" << endl;
}
}
This should work how you expect it to.
However, construction like this:
char option;
while (cin >> option) {
if ((option == '1') || (option == '2')) {
break;
}
else {
cout << "Please enter 1 or 2." << endl;
}
}
cout << "option " << option " << " was selected" << endl;
Is probably better ^_^

I think this looks a better code (at least for the eyes):
int option;
int invalidOption2 = 0;
while(invalidOption2 == 0)
{
try
{
cin>>option;
switch(option)
{
case 1 :
invalidOption2 = 1;
cout<<"option 1 was selected"<<endl;
break;
case 2 :
invalidOption2 = 1;
cout<<"option 2 was selected"<<endl;
break;
default :
error("invalid input");
}
catch(runtime_error& e)
{
cerr <<"Please enter a valid option" << endl;
}
}
If you still think you have problems with int and char with cin then better use :
option = getchar();

I think calling cin twice may be the issue here, but I'm not certain. Something like this should work well too:
char option[80]; // 80 is the standard terminal line length
bool loop = 1;
while(loop)
{
cin >> option;
if (option[1]=='\n') // testing if string is length 1
{
cout << "Please select a valid input\n";
continue; // if not, display error and try again
};
switch(option[0])
{
case '1': loop=0; break; // add whatever before break
case '2': loop=0; break;
default: cout << "please select a valid input\n"; break;
};
};
cout << "Option "<< option << "was selected\n";
I didn't compile this, but it should be okay.

Related

Accept only integer to input

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";
}

C++ input validation: how to accept only certain ints

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;.

Functions to check if the user's input is correct not working

I have created some C++ code that is supposed to check to see if a user's input is correct but it isn't quite working how I want it to. Whenever you type an integer first, and then a couple of characters after it, the terminal spams would you like to try again y/n a couple of times. I have tried to limit the amount of times it can output this, but nothing has worked.
#include <iostream>
#include <limits>
using namespace std;
int again()
{
char yorn = 'q';
cout << "\n Would you like to run this program again? y/n: ";
cin >> yorn;
if (cin.fail()) {
int dof1 = 1; // dof1 stands for don't overflow 1
for (int i = 0; i < dof1; i++) {
cout << "ERROR -- You did not enter a valid symbol";
// get rid of failure state
cin.clear();
// discard 'bad' character(s)
cin.ignore(numeric_limits<streamsize>::max(), '\n');
bool check = again();
if (check == true) {
check = false;
return again();
}
else
return 0;
}
}
switch (yorn) {
case 'y':
return true;
break;
case 'n':
return false;
break;
default:
return again();
break;
}
}
int main()
{
int choice = 0;
cout << "\nWelcome to the Weight Tracker! Type 000 at any time to exit\n"
<< "Choose the option you would like to use below \n"
<< "1) \n"
<< "2) \n"
<< "3) \n"
<< "Option selected: ";
cin >> choice;
if (cin.fail()) {
int dof2 = 1; // dof2 stands for don't overflow 2
for (int i = 0; i < dof2; i++) {
cout << "ERROR -- You did not enter an integer";
// get rid of failure state
cin.clear();
// discard 'bad' character(s)
cin.ignore(numeric_limits<streamsize>::max(), '\n');
bool check = again();
if (check == true) {
check = false;
return main();
}
else
return 0;
}
}
switch (choice) {
case 1:
cout << " use later";
break;
case 2:
cout << " use later";
break;
case 3:
cout << " use later";
break;
default:
cout << "ERROR -- Input invalid \n";
bool check = again();
if (check == true) {
check = false;
return main();
}
else
return 0;
break;
}
return 0;
}
You are missing one cin.ingnore
default:
cout << "ERROR -- Input invalid \n";
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // ADD this line
bool check = again();
To be honest. This code is mess. Please remove recursion from it.

C++ How to enter user values without breaking program

I am trying to get an integer from the user but if they type "ckefkfek" it will cause the program to spam and break. I also want them to enter a float but I get the same problem and no clue how to check for this.
int option = 0;
while (option != 3)
{
cout << "Enter 1, 2, or 3: ";
cin >> option;
switch (option)
{
case 1:
cout << "Enter a float: ";
float myfloat;
cin >> myfloat;
myFunc(myfloat); // must be a float for this function to work.
break;
case 2:
// do stuff
break;
case 3:
// do stuff
break;
default:
cout << endl << "Not a valid option." << endl;
break;
}
}
How can I do this without constant errors? Thank you!
bool input_ok = false;
while (!input_ok)
{
cout << "Enter 1, 2, or 3: ";
if (cin >> option)
{
input_ok = true;
...
}
else
{
cout << "Stop being silly\n";
std::string dummy;
if (cin >> dummy)
cin.clear();
else
throw std::runtime_error("OK, I'm not playing any more");
}
}
Basically if the input can fail, you need to test whether it failed. You test that by checking the state of the stream after reading from it, with cin >> option; if (cin) ..., or by combining the read and test like this: if (cin >> option) ...
If input fails, read whatever couldn't be parsed as an integer and discard it, and try again.

Odd looping situation, don't know what's causing it

Having some trouble with some code and I cannot get to the bottom of it. This code:
int main()
{
int choice;
while (choice != -1)
{
system("cls");
std::cout << "Main Menu: " << std::endl
<< " 1. Encode." << std::endl
<< " 2. Decode." << std::endl
<< "-1 to exit." << std::endl;
std::cin >> choice;
switch (choice)
{
case 1:
encode();
break;
case 2:
decode();
break;
case -1:
break;
}
}
getchar();
return 0;
}
void encode()
{
std::string plainText;
std::string encText = "Test";
std::cout << "Enter text to be encrypted.\n";
getline(std::cin, plainText);
for (int x = 0; x < plainText.length(); x++)
{
//encText += plainText.substr(x, x + 1);
}
std::cout << encText;
getchar();
return;
}
If I enter '1' at the first cin >> choice, I go into encode(), once there, entering any text causes the program to go back to the while, perform system("cls"), and then jumps right back to "Enter text to be encrypted." down in encode().
Any help? I'm clueless.
If you'd like to exit your while loop after encode() or decode(), you have to satisty the while's condition. You can do this by simple setting choice to -1 after the function calls:
case 1:
encode();
choice = -1;
break;
case 2:
decode();
choice = -1;
break;
Just so you're aware, the return at the end of encode() causes the encode() function to finish, not main. That line of code actually does nothing; since there's nothing after it, it would happen anyway.