This question already has answers here:
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed 7 years ago.
I am using netbean ide for c++ study
I would like to force the user to pick only number between 1 to 3
int displayMenu()
{
while(true)
{
cout<<"Please choose one of following options"<<endl;
cout<<"1. deposit"<<endl;
cout<<"2. withdraw"<<endl;
cout<<"3. exit"<<endl;
int input;
cin >>input;
if(input>=1 && input<=3 && cin)
{
return input;
break;
}
else
{
cout<<"You have only 3 options. Please chooses 1,2 or 3"<<endl;
}
}
}
It works fine if the input is int number
If input is less then 1 or greater than 3, this function re-ask user to input number btw 1 and 3.
However, if the input is character such as 'f', it does an infinite loop.
This function know that 'f' is wrong input..
I did my own research in the Internet.
!cin and cin.fail() do not work.
Can you help me?
When you try to read an integer but pass something else, the reading fails and the stream becomes invalid. Whatever caused the error remains in the stream. This leads to infinite loop.
To fix that, clear the error flags and ignore the rest of the line in your else clause:
else
{
cout<<"You have only 3 options. Please chooses 1,2 or 3"<<endl;
cin.clear(); // remove error flags
// skip until the end of the line
// #include <limits> for std::numeric_limits
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
You can modify it like this:
int displayMenu()
{
while(true)
{
cout<<"Please choose one of following options"<<endl;
cout<<"1. deposit"<<endl;
cout<<"2. withdraw"<<endl;
cout<<"3. exit"<<endl;
char input = cin.get(); //read a character
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //skip the rest of characters in cin buffer so that even if a user puts "123" only the first one is taken into account
if(input>='1' && input<='3' && cin) //check whether this is '1', '2' or '3'
{
return input;
break;
}
else
{
cout<<"You have only 3 options. Please chooses 1,2 or 3"<<endl;
}
}
}
Related
This question already has answers here:
cin input (input is an int) when I input a letter, instead of printing back incorrect once, it prints correct once then inc for the rest of the loop
(2 answers)
Closed 2 years ago.
{
valid = true; //Assume the cin will be an integer.
cin >> menuValue;
if (cin.fail()) //cin.fail() checks to see if the value in the cin
//stream is the correct type, if not it returns true,
//false otherwise.
{
cin.clear(); //This corrects the stream.
cin.ignore(); //This skips the left over stream data.
cout << "Please enter an Integer from 1-6 only." << endl;
valid = false; //The cin was not an integer so try again.
}
}
Im trying to make an error checkpoint, where is a user inputs something that isn't an integer, it'll ask them to rein put the number, the only issue is If I were to input something such as jiasdhais, it would print the same message as many times as the length of the input. Any way around this?
Try this:
{
int input;
if( !( std::cin >> input) ){
//in case of fail do stuff
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
//then check for 1-6
//your code ...
}
}
If input is not integer it will be discarded.More specifically if your architecture holds int as 4bytes then the input should be in range -2,147,483,648 to 2,147,483,647, otherwise will be discarded.
This question already has an answer here:
C++ Beginner Infinite Loop When Input Wrong Data Type and Help Evaluate My Code
(1 answer)
Closed 3 years ago.
When I try to call this function and provide a value to variable grade other than integer, the do-while loop kept on executing and don't even prompt for an input to the variable of type char. Kindly help me to figure out why loop kept on executing.
//User Input function
int userInput(){
int grade,question;
char choice='y';
srand(time(0));
do{
//displayMenu();
cout<<endl;
cout<<"Please select grades, use number 1 to 5: ";
cin>>grade;
/*if(grade<1 || grade>5){
cout<<"You have entered an invalid grade!"<<endl;
}
else{
cout<<"Enter number of questions you want to generate: ";
cin>>question;
while(question<1){
cout<<endl;
cout<<"You have entered an invalid number"<<endl;;
cout<<"Enter number of questions you want to generate: ";
cin>>question;
}
cout<<endl;
questionGenerator(grade,question);
cout<<endl;
cout<<"Press n/N to Quit or Press any key and then Enter";
cin>>choice;
system("cls");
}*/
cout<<"Type N/n to Quit or Press Any Key and then Enter"<<endl;
cout<<"Your choice? : ";
cin>>choice;
system("cls");
}while(choice!='n' && choice!='N');
return 0;
}
Well your grade variable is an intteger, so it cant take any other type of variable. If you are going to input a char then why is grade an integer or if you are going to inout a string? If you need this to be possible then maybe try using arrays and start turning them from arrays to: integers floats booleans strings or characters. Also be careful because a char value can be assigned to a number (character code).
I am using get.fail() to check if there's any char in the input, and if there is I would like to give the user a chance to re-enter. However, the program seems to still accept the user input whenever there's an integer in front of the input no matter the case. Say w1 and 1w, the program will tell the user that the it only accepts integers while the latter one accepts the input and moves over to the next line which then causes another problem.
void userChoice(int input){
switch(input)
{
case 1:
insert();
break;
case 2:
display();
break;
case 3:
update_data();
break;
case 4:
delete_position();
break;
case 5:
cout<<"Thank you for using the program\n";
exit(0);
break;
case 6:
tellSize();
break;
default:
cout<<"Not an option\n";
cin>>input;
while(cin.fail())
{
cin.clear();
cin.ignore(INT_MAX, '\n');
cin>>input;
break;
}
userChoice(input);
}
}
Referring to the code above, say I give the input 1w. The program will still execute case 1 as if there's nothing wrong, and then w is somehow passed into the insert() function which is not what I want. I would like the program to let the user re-enter the input no matter if it's 1w or w1, in short I do not want the program to move over to the next line if there's a char in an integer input.
tl;dr:
Why does the code below still execute when the cin is 1w, shouldn't it print "Enter number only" since there's a character in there?
Edit: Here's a quick program I made, to reproduce the error I am facing, I first enter 1h and here's the first bug I'm facing, why is the program still executing when there's a char h in the input? Afterwards in the second input, I enter 2w and the program prints out 2, shouldn't the program loop the while loop since there's a char w in the input?
#include<iostream>
#include<iomanip>
#include<limits>
using namespace std;
void option_1()
{
int amount_input;
cout<<"Enter the amount of cake"<<endl;
cin>>amount_input;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"Enter number only\n";
cin>>amount_input;
}
cout<<amount_input;
}
void options(int input)
{
bool fail;
switch(input)
{
case 1:
option_1();
break;
default:
cout<<"Not an option"<<endl;
cin>>input;
while(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin>>input;
break;
}
options(input);
}
}
void menu(){
int user_input;
cout<<"Enter 1 to print something\n";
cin>>user_input;
options(user_input);
}
int main(){
menu();
}
From your comments, it appears you want integer input exclusively and do not want to allow input of additional character after the integer like 1w, even though 1 would be converted to an int while leaving w unread to be removed by .ignore(...) after your call to .clear(). (as mentioned above, your use of .clear() and .ignore(...) are now correct.
If this is your intent, you need a way to check if there is anything else following the integer input by the user. To do that in a non-blocking way if nothing actually exists, you have a couple of options. (e.g. you can .peek() at the next character -- but you only get one, or you can use a line-oriented input approach) The line-oriented approach allows you to read the entire line of user input into a string and then extract the integer value and check whether there is anything else contained in the line of input.
The most straight forward way is to create a std::basic_stringstream from the line of data read with getline(). This approach, consumes the entire line of user input and provides you with all the tools you need to extract whatever information you may want from the line. It also does this in a way that does not effect any of your subsequent user inputs.
While I would recommend you combine your void menu() and void options(int input) functions so you simply have one function to handle input processing for your menu -- there is nothing wrong with breaking it in two other than the possibility of a few lines of code being duplicated. The following is just a suggestion on how to handle your menu() function to only allow integer input. You can adapt it to the remainder of your code.
You will need a couple of additional includes:
#include <sstream>
#include <string>
I would also #define the first and last acceptable menu entries so you have those constants available in your code in a place that can be easily changed as you add to your menu, e.g.
#define MENUFIRST 1 /* first valid entry */
#define MENULAST 1 /* last valid entry */
(note: that will allow only 1 be entered as a valid menu entry)
To limit you menu() function using the approach outlined above, you could do:
void menu(){
int user_input = 0;
string line, unwanted;
for (;;) { /* loop continually until valid input received */
cout << "\nEnter 1 to print something: ";
if (!getline (cin, line)) { /* read an entire line at a time */
cerr << "(user canceled or unrecoverable stream error)\n";
return;
}
stringstream ss (line); /* create a stringstream from line */
if (!(ss >> user_input)) { /* test if valid integer read */
/* test eof() or bad() */
if (ss.eof() || ss.bad()) /* if not, did user cancel or err */
cerr << "(empty-input or unreconverable error)\n";
else if (ss.fail()) /* if failbit - wasn't an int */
cerr << "error: invalid integer input.\n";
}
else if (ss >> unwanted) { /* are there unwanted chars? */
cerr << "error: additional characters following user_input.\n";
user_input = 0; /* reset user_input zero */
} /* was int outside MENUFIRST-to-MENULAST? */
else if (user_input < MENUFIRST || MENULAST < user_input)
cerr << "error: integer not a valid menu selection.\n";
else /* valid input!, break read loop */
break;
}
options(user_input);
}
The comments should be self-explanatory given the discussion above, but let me know if you have questions. Using the function with the rest of your code (and commenting the unused // bool fail;), you can test whether it meets your requirements, e.g.
Example Use/Output
$ ./bin/menu_int
Enter 1 to print something: w1
error: invalid integer input.
Enter 1 to print something: $#%&^#&$ (cat steps on keyboard) !#$%%^%*()
error: invalid integer input.
Enter 1 to print something: 1w
error: additional characters following user_input.
Enter 1 to print something: -1
error: integer not a valid menu selection.
Enter 1 to print something: 24
error: integer not a valid menu selection.
Enter 1 to print something: 1
Enter the amount of cake
3
3
Also note, your menu() funciton will now properly trap a manual EOF generated by the user pressing Ctrl+d (or Ctrl+z on windows) to cancel input and exit gracefully.
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 8 years ago.
I have a c++ program.I am using a do while loop to re execute the program after every cycle if the user chooses to run it again.The program runs fine on the first loop but on the subsequent runs the program skips requesting for a diver's name.It just prints the prompt for diver's name and number of judges together as shown below.How can i correct that?
On first run,notice the user is prompted to enter the number of judges after entering the diver's name as below
On the subsequent runs,the program does not wait for user to input the diver's name before requesting for the number of judges,it prints the two prompts together and only number of judges can be input as shown below
And here is the main class which holds the logic of execution:
int main()
{
char rerun;
do{
srand(time(NULL));
int number_of_judges=0;
char option,dive;
char dives[3];
string divenames[3];
double** scores;
string diverName="";
cout<<"What is the diver's name? "<<endl;
getline(cin,diverName);
number_of_judges=getjudges();
cout<<number_of_judges;
displayMenu();
for(int i=0;i<3;i++){
cout<<"Enter dive "<<i+1<<" to be judged(A-E)";
cin>>dive;
dive=tolower(dive);
while(!(dive=='a' || dive=='b' || dive=='c' || dive=='d' || dive=='e' ) ){
cout<<"You entered the wrong choice.Choice must be from (a-e)."<<endl;
cout<<"Enter dive "<<i+1<<" to be judged(A-E)";
cin>>dive;
dive=tolower(dive);
}
dive=tolower(dive);
dives[i]=dive;
}
for(int i=0;i<3;i++){
divenames[i]=getDive(dives[i]);
}
scores=getRandom();
getScores(diverName,scores,divenames);
cout<<"Do you want another try?";
cin>>rerun;
while(rerun !='y' && rerun!='n'){
cout<<"You have entered an invalid option.\nPlease try again.";
cin>>rerun;
rerun=tolower(rerun);
}
}
while(rerun=='y' || rerun == 'Y');
std::getchar();
return 0;
}
Any help will be greatly appreciated.
In the line:
cin>>rerun;
a charachter is extracted from the stream. This operation, however, leaves a newline in the buffer. So, when in the next step, you do:
getline(cin,diverName);
you are trying to read all the input up to newline and in the buffer there is already a newline (coming from the previous step): then this operation ends immediately.
The solution is to add an instruction after cin>>rerun of this type:
cin.ignore();
in this manner the newline left in the buffer will be discarded in the next operation.
in my final project, a poker and black jack simulator, my main function doesn't appear to want "cin" to work. The entire project is syntax error free, so that's not a problem, but in order to test to see if it runs or not, I need "cin" to work. The following is my main function, where I seem to be having the trouble:
#include <iostream>
using namespace std;
#include "card.h"
#include "poker.h"
#include "blackJack.h"
void handlePoker(int&);
void handleBlackJack(int&);
//TO DO:
//FIX CIN PROBLEM
//*pulls hair out*
//main function:
//asks the user what game they want to play
//then calls a function for the appropriate
//game chosen
int main()
{ //two choices:
//one for quitting the program
//the other for whichever game they want
char yesOrNo;
char choice;
int totalMoney;
cout<< "please enter a starting amount to bet with"<<endl;
cin>> totalMoney;
do{
//ask the user which game they want
cout<<"would you like to play poker or black jack?"<<endl;
cout<<"input '1' for poker and '0' for blackjack"<<endl;
cin>>choice;
if(choice == '1')
{
handlePoker(totalMoney);
}
else if(choice == '0')
{
handleBlackJack(totalMoney);
}
else
{
cout<<"I'm sorry, the input you entered was invalid"<<endl;
cout<<"please try again"<<endl;
}
cout<<"would you like to try again?"<<endl;
cout<<"('y' for yes, or 'n' for no)"<<endl<<endl;
cin>>yesOrNo;
}while(yesOrNo == 'y' || yesOrNo == 'Y');
}
Everytime I use "cin" in the do while loop, it won't let me input anything. The program never stops for user input.
as it is not, he's the program's output:
"please enter a starting amount to bet with"
*user can enter starting amount here, this "cin" works no problem*
"input '1' for poker and '0' for black jack"
"I'm sorry, the input you entered was invalid"
"please try again"
"would you like to try again?"
"('y' for yes, or 'n' for no)
then the program ends, because none of the choices have any value in them.
I'll include more code if asked, but I believe this is where the problem with it lies.
thank you to all who may help me!
edit: The program does enter the do while loop, and all messages are printed as they should bee, but the program won't let me input any data at all, it doesn't stop to let me input data, it just acts as if they do not exist.
Usually when I see cin ignoring everything and putting me in an infinite loop, that's caused when I enter in invalid input, and never clear the stream state. Namely, entering "A" for a number will do that. The idiomatic way to do this would be something like
while (! (cin >> totalMoney)) {
cout<<"I'm sorry, the input you entered was invalid"<<endl;
cout<<"please try again"<<endl;
cin.clear(); //important
}
// totalMoney holds a valid value now
Try using cin.ignore() instead of just cin for the process to wait for user input
cin>>choice;
cin.ignore();
Check out this link on MSDN for more info