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.
Related
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;
}
I have a question,
Im new to c++ and general with coding.
I have this problem Im coding right now an Loader for a game and want to make a choice menu.
I have this error and I dont know how to fix it.
If you could help I would be happy.
This is my code https://ghostbin.co/paste/x8hz3
int DLL();
int Beta();
int select()
{
int selection;
do
{
selection = menu();
switch (selection)
{
case 1: DLL();
break;
case 2: Beta();
break; cout << "Exiting program.\n\n\n";
}
} while (selection != 2);
return 0;
}
int menu()
{
int choice;
cout << "Loader menu\n";
cout << "--------------------------------\n";
cout << "Normal\n";
cout << "--------------------------------\n";
cout << "1) Beta\n";
cout << "--------------------------------\n";
cout << "2) Dll methods\n";
cin >> choice;
while (choice < 1 || choice > 2) // Check to see if user's input is correct
{
cout << "Invalid Selection. Enter 1, or 2: ";
cin >> choice;
}
return choice;
}
int DLL()
{
cout << "Test" << endl;
}
int Beta()
{
cout << "Test" << endl;
}
You don't need to return anything for select() seemingly. You should declare the main() and write there:
.
select();
.
Important: You haven't defined any proper definition for menu(). On the beginning of the code, just add a single line int menu(); and you're good to go.
As the title says, I'm unable to figure out why this code keep on lopping when the input is not of an integer but a string.
Edit: Seems like you misunderstood my question, let me clarify and pase all the code.
I don't want to quit the program after I finished typing the teacher, because there's a case (case 0) that handle that. What I want to know is why the code keep looping if I enter a string in the part where it's asking for birtdate instead of an integer, but work fine if I enter an integer.
In this case, if an interger where to be entered, the program behaves as expected, but when it's a string, the program keep on looping the part where it asks for the birthdate. Even afte removing the if and else, it's still do the same thing, in which it should crash since there's no error handle.
int main()
{
string tempName;
int tempYear;
char input = 't';
bool exit = 0;
do
{
cout << "Please choose one of the following options:" << endl;
cout << "0. Quit" << endl;
cout << "1. Add new Teacher" << endl;
cout << "2. Add new Assistant" << endl;
cout << "3. Add new TA-personel" << endl;
cout << "4. Show all Staff" << endl;
cout << "You chose: ";
cin >> input;
cout << endl;
switch (input)
{
case '0':
exit = 1;
break;
case '1':
cout << "Please enter the name of the teacher: ";
cin >> tempName;
cin.ignore();
cout << "Please enter the birthdate of the teacher: ";
cin >> tempYear;
cin.ignore();
if (!cin.fail())
{
//Nothing
}
else
{
cout << "The input was not a number!";
cout << "1. Please enter the birthdate of the teacher: ";
cin >> tempYear;
}
break;
case '2':
break;
case'3':
break;
case '4':
break;
default:
cout << "Invalid input!" << endl;
break;
}
} while (exit == 0);
getchar();
return 0;
}
This code (or your full MCVE, anyway, which you neglected to share -.-) will always loop, because you never change the value of the poorly-named variable exit.
Update
Remember when you checked for !cin.fail()? That was the right thing to do, but you didn't unset the fail flag for the next attempt.
cin.clear();
You're not modifying the exit variable inside the loop.
So the condition of the while loop is always true if exit was set to 0 before the loop.
First of all the code is incomplete.
1.You need to change the value of the variable name "exit" to a non-zero value in the switch-case to end the loop which corresponds to the user selecting the exit option.
You need to ask for a new choice from the user inside the do-while loop and before the switch statement starts.
Change the variable type of your tempyear to string.
for example:
char choice;
do
{
cin>>choice;
switch(choice)
{
case '0': exit=1;
break;
}
}while(exit==0)
This will end the loop when the user enters 0
UPDATE
The reason that it goes into infinite loop when you enter a string value in the int variable tempyear is that the bad input flag of cin is set after you enter the string.
To fix it you need to use cin.clear() after cin.ignore() so that the bad input flag is reset and it takes input again- as pointed out by #Lightness Races in Orbit
For some reason, it goes into the cin statement the first time but then skips it every other time in this code. After running it a few times, I realized it goes into the default case for some reason without even asking for the user input. Why?
Here's the code. It's a menu with a huge switch statement. The functions inside the switch statements aren't relevant here since it's just the overall loop.
int main()
{
Document* myDocs = new Document[10];
int docCount = 0;
bool menu = true;
int userInput = 0;
while ( menu == true )
{
//int userInput = 0;
userInput = 0;
cout << "----------------MENU----------------" << endl << endl;
cout << " --------(1) LOAD DOCUMENT (1)--------- " << endl << endl;
cout << "--------(2) OUTPUT DOCUMENT (2)--------" << endl << endl;
cout << " --------(3) ANALYZE DOCUMENT (3)-------- " << endl << endl;
cout << " ------(4) COMPARE TWO DOCUMENTS (4)------ " << endl << endl;
cout << " ----------(5) ENCRYPT (5)---------- " << endl << endl;
cout << "-----------(6) DECRYPT (6)----------" << endl << endl;
cout << "-------------(7) EXIT (7)--------------" << endl << endl;
cin >> userInput;
string docName;
string outputLoc;
switch (userInput)
{
case 1:
// Function
break;
case 2:
// Function
break;
case 3-8:
// Function
break;
default:
break;
}
Basically, I first enter the first userinput. Let's say I enter 1. Then it goes into case 1. But then after it gets out of case 1, it goes into an infinite loop that keeps displaying the menu. Shouldn't it stop at the cin statement? That's what I dont understand.
EDIT::
Case 1 is the primary one i'm worried about since I'm trying them 1 by and 1 and case 1 doesn't work.
This is the full code for case 1:
case 1: // Load Document
{
string inputLoc;
cout << "Please input the document name:" << endl;
cin >> docName;
myDocs[docCount].setName(docName);
myDocs[docCount].id = docCount;
cout << "Input Location: " << endl;
cin >> inputLoc;
myDocs[docCount].loadDocument(inputLoc);
docCount++;
break;
}
I'm starting to speculate there is something wrong with my loadDocument function.
Here is the code for that:
void Document::loadDocument(string name)
{
ifstream myFile(name);
int numOflines = 0;
string theLine;
char words;
while (myFile.get(words))
{
switch (words)
{
case '.':
numOflines++;
break;
case '?':
numOflines++;
break;
case '!':
numOflines++;
break;
}
}
lineCount = numOflines;
setLineCt(numOflines);
arr = new Line[lineCount];
myFile.close();
char theChar;
ifstream myFile2(name);
int key = 0;
if (myFile2.is_open())
{
for ( id = 0; id < lineCount; id++ )
{
while (myFile2>> noskipws>>theChar && theChar != '.' && theChar != '!' && theChar != '?') // Changed from || to &&
{
//myFile2>> noskipws >> theChar;
theLine[key] = theChar;
key++;
}
myFile2>>theChar;
arr[id].setStr(theLine);
}
}
}
Basically I'm trying to load the document and store the word count and line count from it. Is there something wrong in it?
i try to do a simple menu using switch. I also want to do a check if the user made a valid input (Only int from 1 to 4). Entering -4 or 44 is working fine with this check. But if i enter something like "w" it gives me a infinite loop.
I'm guessing i need another if / else with if (!cin) blabla else go ahead with switch.
But i'm not sure how i do that the else is starting the switch.
int menu() {
int enter;
bool exit = false;
do {
cout << "Wie soll angefangen werden: " << endl; //Enter your choice
cout << "1 - Spiel starten" << endl; // do game();
cout << "2 - Highscore " << endl; //do score();
cout << "3 - Quiz starten " << endl; //do quiz();
cout << "4 - Ende " << endl; //end the programm
cin >> enter;
switch (enter) {
case 1:
game();
break;
case 2:
score();
break;
case 3:
showQuizDialog();
break;
case 4:
exit = true;
break;
default:
cout << "Keine gültige Eingabe, nochmal: " << endl; //invalid input, again
void flushCin();
} //end of switch
} while (exit == false);
}//end of menu();
It's because the input is trying to get an integer. When the input is not an integer, the input is left in the buffer, so next time around in the loop the same input is still there.
Also, you are not calling the flushCin function in the default case, you are declaring it. You might want to remove the void keyword. I guess it does the correct thing? (I.e. calling std::cin.ignore() and std::cin::clear().)
Read into a string and try to convert to int:
#include <sstream>
#include <string>
using namespace std;
int menu() {
int enter;
string str;
bool exit = false;
do {
cout << "Wie soll angefangen werden: " << endl; //Enter your choice
cout << "1 - Spiel starten" << endl; // do game();
cout << "2 - Highscore " << endl; //do score();
cout << "3 - Quiz starten " << endl; //do quiz();
cout << "4 - Ende " << endl; //end the programm
cin >> str;
istringstream buffer(str);
buffer >> enter;
switch (enter) {
case 1:
game();
break;
case 2:
score();
break;
case 3:
showQuizDialog();
break;
case 4:
exit = true;
break;
default:
cout << "Keine gültige Eingabe, nochmal: " << endl; //invalid input, again
void flushCin();
} //end of switch
} while (exit == false);
return enter;
}//end of menu();
If entering other things than numbers into an int value directly this might not fit into the reserved space of an int and can result in funny behaviour. So just read into a string first and then interpret it.