while loop infinite validation response to incorrect input - c++

In the case deposit section i have written a loop to validate that the user input is a integer but upon entering something other than an integer it assigns that to the variable credit and repeatedly displays "Please enter an amount greater than £1" i have tried to make it clear the input upon displaying the message so the process can be repeated but i cannot seem to get it to clear the variable of the incorrect input.
#include <iostream>
#include <string>
using namespace std;
enum Menusystem // enum is a function used to convert the list of words below into numbers.
{
ShowMenu, EnterName, Account, Deposit, Withdraw, Balance, Exit
} menu;
int main()
{
string customer; // declaring variables and their data types for the menu options.
string accounttype;
string name;
int credit;
int debit;
int currentbal;
bool exit = false; // declaring variable as boolean setting it to false so that when the loop gets to false it will break the loop and exit the program.
int option = 0; // declares showmenu as a integer and sets value to 0 so that the menu will be displayed upon opening the program as in the code below the menu is displayed if option is equal to 0.
while (!exit) // initiates a while loop so that when the loop gets to false it will break the loop and exit the program.
{
switch (menu) // initiates a switch statement which will allow the program to cycle through menu options depending on the menu option the user selects.
{
case ShowMenu:
cout << "[0] - Show menu\n" // displays menu options to user.
<< "[1] - Enter Full Name\n"
<< "[2] - Enter Account Type\n"
<< "[3] - Deposit Funds\n"
<< "[4] - Withdraw Funds\n"
<< "[5] - Display Balance\n"
<< "[6] - Exit Program\n";
cin >> option;
if (option == 0) menu = ShowMenu;
else if (option == 1) menu = EnterName;
else if (option == 2) menu = Account;
else if (option == 3) menu = Deposit;
else if (option == 4) menu = Withdraw;
else if (option == 5) menu = Balance;
else if (option == 6) menu = Exit;
else menu = ShowMenu; // default case is to show the menu.
break;
case EnterName:
system("CLS");
cout << "Please enter your full name >\n";
cin >> customer;
system("CLS");
menu = ShowMenu;
break;
case Account:
menu = ShowMenu;
break;
case Deposit:
system("CLS");
cout << "Please enter an amount you wish to deposit >\n";
cin >> credit;
while (!(cin >> credit)) cout << "Please enter an amount greater than £1";
{
cin.clear();
cin.ignore(100, '\n');
}
system("CLS");
menu = ShowMenu;
break;
case Withdraw:
system("CLS");
cout << "Please enter an amount you wish to withdraw >\n";
cin >> debit;
system("CLS");
menu = ShowMenu;
break;
case Balance:
cout << credit;
cout << customer;
break;
case Exit:
break;
default:
break;
}
}
return 0;

This statement:
while (!(cin >> credit)) cout << "Please enter an amount greater than £1";
{
cin.clear();
cin.ignore(100, '\n');
}
is not doing what you think it is. It's doing the equivalent of this:
while (!(cin >> credit)) {
cout << "Please enter an amount greater than £1";
}
cin.clear();
cin.ignore(100, '\n');
You need to move the cout statement into the loop, like this:
while (!(cin >> credit)) {
cout << "Please enter an amount greater than £1";
cin.clear();
cin.ignore(100, '\n');
}

Related

Switch Case with While Loop in C++ Menu

I've been building a menu driven console in C++, and I'm currently using switch-case as my options, but now I'm stuck in switch case.
Here's the scenario:
SCENARIO
Explanation:
After inputting invalid option in the main menu, it gives an error which prompts the user to re-input their desired option, now my problem is when the user inputs the correct option for the 2nd attempt, it loops back to the main menu instead of redirecting it to the next menu.
My Goal: To go to the 2nd menu directly from the default without redisplaying the main menu.
My Partial Code:
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int choice;
int booknumber;
int booktitle;
int author;
int datepublished;
int e = 0;
void menu();
void inputbook();
void searchbook();
void borrowbook();
void exit();
//CLASS
class Books
{
public:
int booknumber;
string booktitle;
string author;
string datepublished;
Books(const int booknumber, const string booktitle, const string author, const string datepublished) : booknumber(booknumber), booktitle(booktitle), author(author), datepublished(datepublished) {}
};
//MAIN
int main()
{
while (true)
{
cout << endl;
if (e == 1)
{
break;
}
menu ();
}
return 0;
}
//MENU
void menu()
{
cout << "Welcome to DLC Library System\n";
cout << "Final Project in Advance Programming\n\n";
cout << "PROGRAMMER\n";
cout << "ME\n\n";
cout << "====================================\n";
cout << "[1] -------- Input Book ------------\n";
cout << "[2] -------- Search Book -----------\n";
cout << "[3] -------- Borrow Book -----------\n";
cout << "[4] -------- Exit Program ----------\n";
cout << "====================================\n";
cout << "Input your choice (Number Only): ";
cin >> choice;
switch (choice)
{
case 1:
inputbook ();
break;
case 2:
searchbook ();
break;
case 3:
borrowbook ();
break;
case 4:
exit();
break;
default:
while (choice < 1 || choice > 4)
{
cout << "Wrong Option\n";
cout << "Input your choice (Number Only): ";
cin >> choice;
if (choice < 1 || choice > 4)
{
continue;
}
}
}
}
// INPUT BOOK
void inputbook ()
{
int booknumber;
string booktitle;
string author;
string datepublished;
cout << "INPUT NEW BOOK\n\n";
cout << "Book Number: \n";
cin >> booknumber;
cout << "Book Title: \n";
cin >> booktitle;
cout << "Author: \n";
cin >> author;
cout << "Date Publish: \n";
cin >> datepublished;
Books(booknumber,booktitle, author, datepublished);
cout << "====================================\n";
cout << "[1] -------- Try Again? ------------\n";
cout << "[2] -------- Return to Menu --------\n";
cout << "[3] -------- Exit Program ----------\n";
cout << "====================================\n";
cout << "Input your choice (Number Only): ";
cin >> choice;
switch (choice)
{
case 1:
inputbook ();
break;
case 2:
menu ();
break;
case 3:
exit();
default:
cout << "Wrong Option";
}
}
It's a good idea to avoid repeating code. Here, you have a default case that is essentially an input loop, whereas you could have done that input loop at the start. So the way you wrote it, you still need a loop around the whole thing, plus more logic which makes the code harder to read and more bug-prone.
Why not simply:
cout << "====================================\n";
cout << "[1] -------- Input Book ------------\n";
cout << "[2] -------- Search Book -----------\n";
cout << "[3] -------- Borrow Book -----------\n";
cout << "[4] -------- Exit Program ----------\n";
cout << "====================================\n";
int choice;
bool validInput = false;
while (!validInput)
{
cout << "Input your choice (Number Only): ";
if (!(cin >> choice)) {
std::cerr << "Aborted\n";
return;
}
validInput = (choice >= 1 && choice <= 4);
if (!validInput) {
std::cout << "Invalid input\n";
}
}
switch(choice)
{
// ...
}
Now it's up to you to make your input routine more robust if you choose. Notice I've already bailed out of the function if the input fails. That could be from a stream error, but it could also be if the user enters a non-integer value.
You may instead wish to read your input as a string using std::getline and then convert that to an integer with std::stoi or parse the value from a std::istringstream.
Instead
continue;
try calling
inputbook();
so it won't go back.
That's a problem you are facing because you called switch-case again which is "continue". That's why it goes back to the menu when the user inputs the acceptable range of int you just set.
Just modify the code as below, and handle the valid input verification before entering the switch, in this way you can simply mitigate the issue you had!
cin >> choice;
while (choice < 1 || choice > 4)
{
cout << "Wrong Option\n";
cout << "Input your choice (Number Only): ";
cin >> choice;
if (choice < 1 || choice > 4)
{
continue;
}
}
switch (choice)
{
case 1:
inputbook ();
break;
case 2:
searchbook ();
break;
case 3:
borrowbook ();
break;
default:
exit();
break;
}

Switch statements with while loops

do{
cout << "Select an option from the Menu: ";
cin >> choice;
// Validate the menu selection
while ((choice < 1) || (choice > 3)){
cout << "Incorrect input!, please enter an option from 1 to 3."<<endl;
cout<<"Enter your choice: ";
cin >> choice;
}
// Processing the users choice
if (choice != 3){
// Compute conversions
switch (choice){
case 1:
cout<<""<<endl;
cout<<"You have selected to convert Fijian Dollars to Vanuatuan Vatu."<<endl;
cout<<"Enter the amount you wish to convert: ";
cin >> amount;
conversion = amount * FJD_to_Vatu_Rate;
break;
case 2:
cout<<""<<endl;
cout<<"You have selected to convert Fijian Dollars to Samoan Tala."<<endl;
cout<<"Enter the amount you wish to convert: ";
cin >> amount;
conversion = amount * FJD_to_Tala_Rate;
break;
case 3:
cout<<"Here the history will be shown"<<endl;
cout<<""<<endl;
cout<<"Do You want to perform another conversion? (Y/N) ";
cin >> repeat;
if (repeat == 'Y'){
(This is what i want to know)
}
cout<<"Thank you for using this program, goodbye!"<<endl;
return 0;
}
// Display the monthly charges
cout << fixed << showpoint << setprecision(2);
cout << "The converted amount is: " << conversion << endl;
cout <<""<<endl;
}
} while (choice != 3);
cout<<"Thank you for using this program, goodbye!"<<endl;
return 0;
}
The above is my part of my code for a currency converter, can anyone tell me if what to do in the section where it says "this is what i want to know" so that the program asks user to enter a choice so it can process it and use the choice to compute using one of the other cases.
Thanks
Remove your if statement before switch because case 3: will never be executed in this case.
do{
cout << "Select an option from the Menu: ";
cin >> choice;
// Validate the menu selection
while ((choice < 1) || (choice > 3)){
cout << "Incorrect input!, please enter an option from 1 to 3."<<endl;
cout<<"Enter your choice: ";
cin >> choice;
}
// Processing the users choice
// Compute conversions
switch (choice){
case 1:
cout<<""<<endl;
cout<<"You have selected to convert Fijian Dollars to Vanuatuan Vatu."<<endl;
cout<<"Enter the amount you wish to convert: ";
cin >> amount;
conversion = amount * FJD_to_Vatu_Rate;
break;
case 2:
cout<<""<<endl;
cout<<"You have selected to convert Fijian Dollars to Samoan Tala."<<endl;
cout<<"Enter the amount you wish to convert: ";
cin >> amount;
conversion = amount * FJD_to_Tala_Rate;
break;
case 3:
cout<<"Here the history will be shown"<<endl;
cout<<""<<endl;
cout<<"Do You want to perform another conversion? (Y/N) ";
cin >> repeat;
if (repeat == 'Y'){
(This is what i want to know)
}
cout<<"Thank you for using this program, goodbye!"<<endl;
return 0;
// Display the monthly charges
cout << fixed << showpoint << setprecision(2);
cout << "The converted amount is: " << conversion << endl;
cout <<""<<endl;
}
} while (choice != 3);
cout<<"Thank you for using this program, goodbye!"<<endl;
return 0;
}
To restart do-while loop use continue. Logically you should print history first first, then do question\check.

c++ Input Validation printing twice?

Don't know why it is printing twice. This is just practice I am trying to use cin.clear() / cin.ignore though. Trying to write a menu with functions inside switch statements.
#include <iostream>
#include <iomanip>
using namespace std;
void showMenu();
void showFees(double, int);
int main()
{
int choice;
int months;
const int ADULT_CHOICE = 1;
const int CHILD_CHOICE = 2;
const int SENIOR_CHOICE = 3;
const int QUIT_CHOICE = 4;
const double ADULT = 40.0;
const double CHILD = 20.0;
const double SENIOR = 30.0;
do
{
showMenu();
cin >> choice;
while (choice < ADULT_CHOICE || choice > QUIT_CHOICE)
{
cout << "Please enter a valid menu choice: ";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
if (choice != QUIT_CHOICE)
{
cout << "For how many months? ";
cin >> months;
switch (choice)
{
case ADULT_CHOICE:
showFees(ADULT, months);
break;
case CHILD_CHOICE:
showFees(CHILD, months);
break;
case SENIOR_CHOICE:
showFees(SENIOR, months);
break;
}
}
} while (choice != QUIT_CHOICE);
system("pause");
return 0;
}
void showMenu()
{
cout << "\nHealth Club Membership Menu" << endl << endl;
cout << "1. Standard Adult Membership" << endl;
cout << "2. Child Membership" << endl;
cout << "3. Senior Citizen Membership" << endl;
cout << "4. Quit the Program" << endl << endl;
cout << "Enter your choice: ";
}
void showFees(double memberRate, int months)
{
cout << "The total charges are $" << (memberRate * months) << endl;
}
This is what it's printing. I'm fairly new c++, so I'm not really sure what's wrong. Is it the spacing? No clue.
Health Club Membership Menu
1. Standard Adult Membership
2. Child Membership
3. Senior Citizen Membership
4. Quit the Program
Enter your choice: 0
Please enter a valid menu choice: Please enter a valid menu choice: 0
Please enter a valid menu choice:
You have forgotten to read input again:
cin >> choice;
while (choice < ADULT_CHOICE || choice > QUIT_CHOICE)
{
cout << "Please enter a valid menu choice: ";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
You read your input once. Then you go into the while check choice, You do cin.clear() and cin.ignore() and once again your loop executes as no new data has been passed: This should do the job:
cin >> choice;
while (choice < ADULT_CHOICE || choice > QUIT_CHOICE)
{
cout << "Please enter a valid menu choice: ";
cin.clear();
cin.ignore(INT_MAX, '\n');
cin >> choice;
}
The input stream looks like this:
0\n
You first read the 0, and now the stream is
\n
The 0 is invalid, so you print "Please enter a valid menu choice: " and skip over the newline.
The stream is now empty.
Since the value of choice hasn't changed, it's still invalid and you print "Please enter a valid menu choice: " again.
This time the input stream is empty, so the ignore has to wait for the next newline, and that's why you're getting two outputs only the first time.
If you instead had done the output after you were done with the input processing:
cin.clear();
cin.ignore(INT_MAX, '\n');
cout << "Please enter a valid menu choice: ";
the output woldn't have been repeated.
A different bug is that the loop never exits, even if you input a valid value.
The reason for this is that you never read a new value for choice.
You need to add
cin >> choice;
at the end of the validation loop.
Problem is here:
while (choice < ADULT_CHOICE || choice > QUIT_CHOICE)
{
cout << "Please enter a valid menu choice: ";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
Try this code. You must read value to variable choice again.
while (choice < ADULT_CHOICE || choice > QUIT_CHOICE)
{
cout << "Please enter a valid menu choice: " << endl;
cin >> choice;
cout << endl;
}

Case inside switch looping non-stop, even though i had break

I just started learning c++, i am making this menu driven program using the switch case.
The problem is, when i enter one of the option it loops infinitely although i already used break.
while (choice != 3)
{
switch(choice)
{
case 1:
{
int TIME;
cout << "Input time: " << endl;
cin >> TIME;
string ACTIVITY;
cout << "Input activity: " << endl;
cin >> ACTIVITY;
todo.addNode(TIME, ACTIVITY);
break;
}
case 2:
{
int DELETE;
cout << "Which activity that you want to delete: " << endl;
cin >> DELETE;
todo.removeIndex(DELETE);
break;
}
default:
{
cout << "Invalid input";
break;
}
}
}
For example, if i pressed 1, the program asks for the time and activity endlessly without breaking. When i pressed any numbers other than 1,2, or 3, it prints the invalid input endlessly.
Am i missing something?
currently your code breaks out of the switch statement, but cannot come out of the while loop as condition is not taken as input inside it.
To come out of the while loop, you need a flag to break outer while loop:
int flag=0;
while (choice != 3)
{
switch(choice)
{
case 1:
{
int TIME;
cout << "Input time: " << endl;
cin >> TIME;
string ACTIVITY;
cout << "Input activity: " << endl;
cin >> ACTIVITY;
todo.addNode(TIME, ACTIVITY);
break;
}
case 2:
{
int DELETE;
cout << "Which activity that you want to delete: " << endl;
cin >> DELETE;
todo.removeIndex(DELETE);
break;
}
default:
{
cout << "Invalid input";
flag=1;
break;
}
}
if(flag == 1)
{
break;
}
}
this is one implementation. your flag=1; statement might be else-where.
Note1: Dont use return in place of break, if there is something else to be processed in the function after this while loop. Otherwise, you can return from the if(flag == 1) condition.
Note2: Another option is to get choice input from the user in the default case. like so cin >> choice; the problem is your while loop does not take choice after it enters the loop because of this choice does not change and hence loops endlessly.

issue with c++ code skipping get line statement

Hey guys i am having an issue with an assignment I am working on.
The code is as follows:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
class payroll
{
private:
char empnum[10];
char empfirstname[150];
char emplastname[150];
char empsin[9];
char empdob[10];
char empphone [15];
char empstreet[100];
char empcity[60];
char empprovince[150];
char empcountry[200];
char empstatus[50]; //Employee status. EX: Terminated, On leave, Active etc.
int empsalaryei;
int empsalaryfedtax;
int empsalarycpp;
int empsalarynet;
int empsalarygross;
public:
void addrec(void);
void modrec(void);
void viewrec(void);
void exit(void);
};
payroll rec;
payroll emp;
ifstream inFile1;
ifstream inFile2;
bool check = false;
int main()
{
system("CLS");
char ch;
do
{
cout<<"1. Add an employee\n";
cout<<"2. Modify employee record\n";
cout<<"3. View employee record\n";
cout<<"0. Exit\n";
cout<<"Please choose an item: ";
if (check == true)
{
system("CLS");
ch=0;
}
else
cin>>ch;
switch(ch)
{
case '1':
emp.addrec();
break;
case '2':
emp.modrec();
break;
case '3':
emp.viewrec();
break;
case '0':
emp.exit();
return 0;
}
}while(ch !=0);
return 0;
}
void open_employee_info() //function to open employee data file
{
string filename1 = "employee-details.dat"; //define which file to open
inFile1.open(filename1.c_str()); //open our payroll file
if(inFile1.fail()) //if our file open fails....
{
cout << "\nSorry the file was not opened successfully"<< "\n Please check that the file does exist or create it" << endl;
exit(1);
}
cout << "\n The file was opened successfully" << endl;
}
void open_payroll_info() //function to open payroll salary information file
{
string filename2 = "payroll-info.dat"; //define file name
inFile2.open(filename2.c_str());
if(inFile2.fail())
{
cout << "\nSorry the file was not opened successfully"<< "\n Please check that the file does exist or create it" << endl;
exit(1);
}
cout << "\n The file was opened successfully" << endl;
}
void payroll::addrec(void) //Record adding
{
char userinputadd = ' ';
cout << "\nPlease Enter the Employee number: ";
gets(rec.empnum);
cout << "\nPlease Enter the Employee's First Name: ";
gets(rec.empfirstname);
cout << "\nPlease Enter the Employee's Last Name: ";
gets(rec.emplastname);
cout << "\nPlease Enter the Employee's Date of Birth (mmddyyyy): ";
gets(rec.empdob);
cout << "\nPlease Enter the Employee's Social Insurance Number: ";
gets(rec.empsin);
cout << "\nPlease Enter the Employee's Phone Number: ";
gets(rec.empphone);
cout << "\nPlease Enter the Employee's Address: ";
gets(rec.empstreet);
cout << "\nPlease Enter the Employee's City: ";
gets(rec.empcity);
cout << "\nPlease Enter the Employee's Province: ";
gets(rec.empprovince);
cout << "\nPlease Enter the Employee's Country: ";
gets(rec.empcountry);
cout<<"\nPlease Enter the Employee's Status: ";
gets(rec.empstatus);
cout << "\nPlease Enter the Employee's Weekly Gross Salary: ";
cin >> rec.empsalarygross;
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputadd;
if (userinputadd =='y' || userinputadd =='Y')
main();
else
exit();
}
void payroll::modrec(void) //Record Modification
{
system("CLS");
int empmodnum=0;
check = false;
char userinputmod = ' ';
cout<<"\nEnter the employee number for the record you would like to modify: ";
cin>>empmodnum;
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputmod;
if (userinputmod =='y' || userinputmod =='Y')
main();
else
exit();
}
void payroll::viewrec(void) //Record viewing
{
system("CLS");
check = false;
char userinputview = ' ';
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputview;
if (userinputview =='y' || userinputview =='Y')
main();
else
exit();
}
void payroll::exit(void)
{
inFile1.close();
inFile2.close();
check = true;
}
So on the front menu if you hit 1 to add a record you will see it skips the first cin statement being employee number.
Does anyone have an idea why this would occur?
You are leaving the newline character in your input stream after you press 1.
Consider all of the keys that you are typing. If you type "1" for addrec, then an employee ID of 987, then the name "John", your input stream looks like this:
1, \n, 9, 8, 7, \n, J, o, h, n, \n
You read the first character with cin >> ch. The next input statement you have is gets().
gets() reads, correctly, all of the characters up to the next newline. Since you still have the newline that follows '1', that first line will be read as blank.
Try adding this somewhere to your program:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You probably have a buffer issue so you need to flush stdin. Check google for details.