input validation c++ with menu - c++

i have this menu like so.
int choice;
cout <<"1: Exit\n2: Print Mark\n3: Print Name"<<endl;
cin >> choice;
while (choice != 1 && choice != 2 && choice != 3)
{
cout << "Invalid Choice <<endl;
cout <<"1: Exit\n2: Print Mark\n3: Print Name"<<endl;
cin >> choice;
}
so that is what i have so far but when ever i input letters it terminates is there a easier way to test for invalid inputs.
i know there is something like cin.fail()
but not sure on how to implement it

This simple line skip when it's a bad input.
td::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore and skip bad input

okay you can structure your code like this
do {
if (choice ==1)
{
exit(1);
}else if (choice==2)
{
//code
}
}else if (choice==3)
{
//code
}
}else if (choice==4)
{
//code
}else{
cout <<"Please enter a correct option"<<endl;
cin.clear();
string choice;
cin>>choice;
}
}while(!cin.fail())
This works 100%

If it is possible for changing that int to char you can do like this.
Its easy this way.
char choice;
cout <<"1: Exit\n2: Print Mark\n3: Print Name"<<endl;
cin >> choice;
while (choice != '1' && choice != '2' && choice != '3')
{
cout << "Invalid Choice <<endl;
cout <<"1: Exit\n2: Print Mark\n3: Print Name"<<endl;
cin >> choice;
}
If you want to get the choice back as int, you can do
int choiceInt = choice - '0';

First take a string as input then try to cast it to int to see if it is valid. You can make it like this (if using c++11):
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int choice = -1;
while (true) {
string input;
cout << "1: Exit\n2: Print Mark\n3: Print Name" << endl;
cin >> input;
try {
choice = stoi(input);
if (choice > 0 && choice < 4) {
break;
}
} catch (const std::exception& e) {
}
cout << "Invalid input" << endl;
}
cout << "Your valid choice: " << choice << endl;
}

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

How to repeat input command if user input is invalid with a string variable - C++

So I have very little coding experience and the code I wrote has this problem of asking the user to input again if correctly choosing "yes" the first time. It works correctly if the user inputs "no" or if the user writes an invalid option, the next set of questions would work. I haven't found any examples dealing with string variables without using arrays. Thanks -
P.S. I know its crappy form but I'm just trying to get it to work.
#include<string>
#include<iostream>
using namespace std;
int main() {
string choice;
cout<<"Do you choose to go fight in the war??\n\n";
cout << "choose yes or no\n";
cin >> choice;
while(choice != "yes" || choice != "no")
{
cout << "pls enter again\n";
cin >> choice;
if(choice == "no")
{
cout << "you live";
break;
}
else(choice == "yes");
{
cout << "you die";
break;
}
}
}
Instead of else you need else if:
else if (choice == "yes") {
cout << "you die";
break;
}
One way is to use an infinite loop to handle the input. If a valid input is given, break the loop.
using namespace std;
int main()
{
string choice;
cout << "Do you choose to go fight in the war??\n\n";
cout << "choose yes or no\n";
while (true) {
cin >> choice;
if (choice == "no") {
cout << "you live";
break;
}
else if (choice == "yes")
{
cout << "you die";
break;
}
else {
cout << "pls enter again\n";
}
}
return 0;
}
When I started learning coding, I faced the same logic problems like what you are struggling at the moment. I just think that you are having problems with syntax and coding logic. Hope that my code can somehow help!
#include <iostream>
#include <string>
using namespace std;
int main() {
string choice;
do {
cout << "Do you choose to go fight in the war??\n";
cout << "Choose yes or no\n";
cin >> choice;
if (choice == "no") {
cout << "you live\n";
break;
} else if (choice == "yes") {
cout << "you die\n";
break;
}
} while (choice != "yes" && choice != "no");
return 0;
}
Use do- while loop for string input and after the loop apply conditions
#include<iostream>
using namespace std;
main()
{
String choice;
cout << "Do you choose to go fight in the war??\n\n";
cout << "choose yes or no\n";
do
{
cin >> choice;
If(choice != "yes" || choice != "no")
Cout<<"please enter again";
}
while (choice != "yes" || choice != "no");
If (choice == "no")
{
cout << "you live";
}
else
{
cout << "you die";
}
}

C++ can't update one of my variables

I had this school assignment to build an atm machine. I got it to work but if I deposit or withdrawal money and view my account balance later its still not updated. Can someone tell me what I am doing wrong and any suggestion on how to make my code better, in general, would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;
void WelcomeMenu();
void Menu();
void userChoiceDeposite(double accountbalance);
void userChoiceWithdraw(double accountbalance);
void userChoiceView(double accountbalance);
void printReceipt();
int main ()
{
//clear receipt.txt from previous transactions
ofstream clearFile("Receipt.txt");
clearFile.close();
//Declaring variables
string userInput;
char userAction;
//prompt user for input, start the program or quit
cout <<"Enter start to continue, or Q/q to quit ";
getline (cin, userInput);
cout <<endl;
//check the input
if ((userInput == "q") || (userInput == "Q"))
{
cout <<"Have a nice day!" <<endl;
return 0;
}
else if (userInput == "start")
{
const int sizeLimit = 50;
string firstName[sizeLimit], lastName[sizeLimit], passWord[sizeLimit];
double accountBalance[sizeLimit];
int count = 0;
ifstream readFile("Accounts.txt");
while (!readFile.eof())
{
readFile >> firstName[count];
readFile >> lastName[count];
readFile >> passWord[count];
readFile >> accountBalance[count];
count++;
}
//ask for username/pw
string fName, lName, pwd;
double accountbalance;
bool exists = false;
do
{
cout <<"Enter First Name: ";
cin >> fName;
cout <<"Enter Last Name: ";
cin >>lName;
cout <<"Enter Password: ";
cin >> pwd;
for (int i=0; i<sizeLimit; i++)
{
if (firstName[i] == fName)
{
if (lastName[i] == lName)
{
if (passWord[i] == pwd)
{
exists = true;
accountbalance = accountBalance[i];
}
}
}
}
}
while (exists == false);
//if correct display menu
WelcomeMenu();
cin >> userAction;
//while login is valid (true)
while (userAction != 'q')
{
if (userAction == 'D' || userAction == 'd')
{
userChoiceDeposite(accountbalance);
}
else if (userAction == 'W' || userAction == 'w')
{
userChoiceWithdraw(accountbalance);
}
else if (userAction == 'V' || userAction == 'v')
{
userChoiceView(accountbalance);
}
else if (userAction == 'P' || userAction == 'p')
{
printReceipt();
return 0;
}
else
{
cout <<"Have a nice Day" <<endl;
return 0;
}
Menu();
cin >> userAction;
}
}
else
{
cout <<"Input Error..." <<endl;
}
return 0;
}
//welcome menu display function
void WelcomeMenu()
{
cout <<"Welcome to your account " <<endl;
cout <<endl;
cout <<"[D/d] Deposit Money" <<endl;
cout <<"[W/w] Withdraw Money" <<endl;
cout <<"[V/v] View Account Balance" <<endl;
cout <<"[Q/q] Quit" <<endl;
}
//function after action was taken (add print option)
void Menu()
{
cout <<endl;
cout <<"[D/d] Deposit Money" <<endl;
cout <<"[W/w] Withdraw Money" <<endl;
cout <<"[V/v] View Account Balance" <<endl;
cout <<"[P/p] Print Receipt and quit" <<endl;
cout <<"[Q/q] Quit" <<endl;
}
//deposit function
void userChoiceDeposite(double accountbalance)
{
int depositMoney;
cout <<"Enter the ammount of money you want to deposit. Max $10000" <<endl;
cin >> depositMoney;
if ((depositMoney > 0) && (depositMoney <= 10000))
{
accountbalance = accountbalance + depositMoney;
ofstream saveAction("Receipt.txt", ios_base::app);
saveAction << "You made a deposit of $" <<depositMoney <<endl;
saveAction.close();
}
else
{
cout <<"Incorrect ammount" <<endl;
return userChoiceDeposite(1);
}
}
//withdraw function
void userChoiceWithdraw(double accountbalance)
{
int withdrawMoney;
cout <<"Enter the ammount of $ you want to withdraw:";
cin >> withdrawMoney;
if (accountbalance < withdrawMoney)
{
cout <<"You dont have that much money"<<endl;
return userChoiceWithdraw(1);
}
else
{
accountbalance = accountbalance - withdrawMoney;
ofstream saveAction("Receipt.txt", ios_base::app);
saveAction << "You withdrew $" <<withdrawMoney <<endl;
saveAction.close();
}
}
//view function
void userChoiceView(double accountbalance)
{
cout <<"Your account balance is $" <<accountbalance <<endl;
ofstream saveAction("Receipt.txt", ios_base::app);
saveAction << "You viewed your account balance" <<endl;
saveAction.close();
}
//print receipt function
void printReceipt()
{
ofstream saveAction("Receipt.txt", ios_base::app);
saveAction << "" <<endl;
saveAction << "" <<endl;
saveAction << "" <<endl;
saveAction << "Thank you! Come again!" <<endl;
saveAction.close();
}
You are only changing the value that you pass into the function (thus not changing the accountbalance outside of the function). For your methods where you need to update the accountbalance you either need to:
Pass by reference
Create a global variable
use a return value to update the account balance
Try one of these and see how it goes.

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

c++ getline function does not let me input

So i have a palindrome program and here are the codes:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
void palindrome();
void compareTwoInt();
bool validation(const string&);
int main()
{
int selection;
cout << "\t\t\t MENU\n";
cout << "\t\t\t ----\n";
cout << "\t\t\t1. Palindrome";
cout << "\n\t\t\t2. Compare Two Integers";
cout << "\n\t\t\t3. End program\n";
cout << "\n\t\t\tEnter your choice : ";
cin >> selection;
while (selection < 0 || selection > 4)
{
cout << "\t\t\nInvalid entry. Please enter an appropriate entry.";
cout << "\n\n \t\t\tEnter your choice: ";
cin >> selection;
}
if (selection == 1)
{
cout << "Enter a word, phrase, sentence: \n";
string input;
getline(cin, input);
string input2;
for (unsigned int i = 0; i < input.length(); i++)
{
if (isalnum(input[i]))
{
input2 += toupper(input[i]);
}
}
cout << input2 << endl;
if (validation(input2))
{
cout << "The phrase is a palindrome!" << endl;
cout << "Press <Enter> key back to menu" << endl;
}
else
{
cout << "The phrase is not a palindrome!" << endl;
cout << "Press <Enter> key back to menu" << endl;
}
fflush(stdin);
cin.get();
system("cls");
return main();
}
else if (selection == 2)
{
compareTwoInt();
fflush(stdin);
system("cls");
return main();
}
else if (selection == 3)
{
cout << "\t\t Good Bye. Press <Enter> key to End the program.\n";
}
fflush(stdin);
cin.get();
return 0;
}
void compareTwoInt()
{
int first, second;
cout << "\n\nEnter your positive integer : ";
cin >> first;
cout << "\nEnter your positive integer : ";
cin >> second;
fflush(stdin);
cin.get();
}
bool validation(const string& input)
{
return input == string(input.rbegin(), input.rend());
}
for some reason when i choose 1 for the palindrome, it doesn't let me write the words, (in another words, it doesn't let me input)
the console just says:
Enter a word, phrase, sentence:
The phrase is palindrome!
Press key back to menu
Anybody have an idea how to fix this?
Thanks in advance!
When you choose 1 for the palindrome, you hit enter. Thus your input consists of the number 1 followed by a newline. Your cin >> selection; reads the number 1 and then your getline(cin, input); reads the newline, which it interprets as an empty line. You have written no code to do anything sensible with the newline character input after the number, so nothing sensible happens.
Try typing 1foof<enter> instead. Your code will read that as a 1 followed by a line containing foof.