Java do-while loop prints menu 3 times instead of once [duplicate] - java

This question already has answers here:
How to read a single char from the console in Java (as the user types it)?
(7 answers)
Closed 3 years ago.
I'm a new programmer. I'm coding a user menu and I've a question on the do-while loop. When main() calls my first method containing my first loop it works as expected. However, when the user selects makes a choice and customerMenu() is called, it prints the menu 3 times. Why is this? Is there a mistake in my code?
public class Runner {
public static void main(String[] args) {
Menu m = new Menu ();
m.mainMenu();
}
}
public class Menu {
private char choice;
public void mainMenu () {
try {
do {
System.out.println("Create Order");
System.out.println("View Orders");
System.out.println("Customers");
System.out.println("Employees");
choice = (char) System.in.read();
} while (choice < '1' || choice > '4');
System.out.println("\n");
switch (choice) {
case '1':
System.out.println("Create Order page");
break;
case '2':
System.out.println("View Orders page");
break;
case '3':
customerMenu();
//System.out.println("Customers page");
break;
case '4':
System.out.println("Employees page");
break;
}
} catch (Exception e) {
System.out.println("Error");
}
}
// Do loop prints 3 times
public void customerMenu () {
try {
do {
System.out.println("Add a Customer");
System.out.println("Edit a Customer");
System.out.println("Delete a Customer");
choice = (char) System.in.read();
} while (choice < '1' || choice > '3');
System.out.println("\n");
switch (choice) {
case '1':
System.out.println("Add a Customer action");
break;
case '2':
System.out.println("Edit a Customer action");
break;
case '3':
System.out.println("Delete a Customer action");
break;
}
} catch (Exception e) {
System.out.println("Error");
}
}
}

There are no problems with the logic of your program but instead of using System.in.read () use either Scanner or BufferedReader. I can only guess that the three other characters that System.in.read () read are the null byte, line feed, and carriage return.

I just tried out the code (link to test env) and for me the menu is printing two times, not three.
The reason it prints twice is because System.in.read() reads in the next byte of data. When you type '3' and hit enter, that sends two bytes of data to the input stream. One byte for the 3 and one byte to indicate 'newline'.
The first time the do-while loop is entered, it reads in the 'newline' byte. That causes the loop to run a second time. The second time around, there's no more bytes to read so it waits for input for user.

Hi there i found your're mistake, i am not good with java. hmm maybe just printing the choice variable you will find your answer.
in mainmenu you have the choice variable and when you called customerMenu on the do while loop the choice variable is read again.
solution create another variable for customerMenu.

Related

Program that asks a multiple-choice question won't show the user an answer after an invalid character is entered

I am trying to make a program where the user has to answer a multiple choice question. The program works completely fine when the user enters A, B, C, or D. But if they enter "Z" for example, it stops working at a certain point. The program will proceed as prompted by saying "Invalid answer, please enter A, B, C, or D." But when you select A, B, C, or D, the program suddenly ends instead of showing whether or not the user was correct.
I tried to call the getAnswer() method again as the default case in the switch statement, so the program will ask the user for their choice again. Before I added this line, it didn't do that at all. However, it's still not following through with that last step. Here's the code:
// Call the method that will ask the user the question.
askQuestion();
// Call the method that will allow the user to answer.
getAnswer();
switch(userChoice)
{
case 'a':
case 'A':
System.out.println("Incorrect! 'Switch' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
break;
case 'b':
case 'B':
System.out.println("Correct!");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
break;
case 'c':
case 'C':
System.out.println("Incorrect! 'Float' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
break;
case 'd':
case 'D':
System.out.println("Incorrect! 'True' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
break;
default:
System.out.println("Invalid character.");
// Repeats the getAnswer method to retrieve a valid character.
getAnswer();
}
}
// method that will ask the question
public static void askQuestion()
{
// Show the user the possible answers for the multiple choice questions.
System.out.println("Which of these is NOT a Java key word?");
System.out.println("A: switch");
System.out.println("B: keyboard");
System.out.println("C: float");
System.out.println("D: true");
}
// method that will retrieve the answer from the user
public static char getAnswer()
{
// create another Scanner object
Scanner keyboard = new Scanner(System.in);
// Tell the user to select their answer and store it in a variable.
System.out.println("Select your answer by pressing A, B, C, or D.");
String input = keyboard.nextLine();
userChoice = input.charAt(0);
// Return the user's answer to main.
return userChoice;
}
Ideally, if the user presses Z, but then presses A the next time around, it will tell the user is wrong, but the program is just ending instead of providing feedback. What am I missing?
It's best to use a loop here. You keep looping until the user enters a valid response:
askQuestion();
while (true) {
userChoice = getAnswer();
switch(userChoice)
{
case 'a':
case 'A':
System.out.println("Incorrect! 'Switch' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
...
default:
System.out.println("Invalid character.");
}
}
Note that you don't need the break statements after each System.exit(0) call.
You could move the askQuestion() call inside the while loop if you wanted to re-ask the question on a bad input.
you can use a recurring method call when an invalid answer is received
public void doProcess(){ //this will keep getting called until a valid key is read.
askQuestion();
userChoice = getAnswer();
switch(userChoice)
{
case 'a':
case 'A':
case 'b':
//program will exit/ correct wrong ans etc etc
break;
default:
//call itself again
doProcess();
}
}
Your switch case only checks for a single time only for the first answer.
You can have function for finidng the answer itself.
import java.util.Scanner;
public class Main
{
// method that will ask the question
public static void askQuestion()
{
// Show the user the possible answers for the multiple choice questions.
System.out.println("Which of these is NOT a Java key word?");
System.out.println("A: switch");
System.out.println("B: keyboard");
System.out.println("C: float");
System.out.println("D: true");
}
// method that will retrieve the answer from the user
public static char getAnswer()
{
// create another Scanner object
Scanner keyboard = new Scanner(System.in);
// Tell the user to select their answer and store it in a variable.
System.out.println("Select your answer by pressing A, B, C, or D.");
String input = keyboard.nextLine();
char userChoice = input.charAt(0);
// Return the user's answer to main.
return userChoice;
}
public static void main(String[] args) {// Call the method that will ask the user the question.
askQuestion();
// Call the method that will allow the user to answer.
char userChoice = getAnswer();
while(!checkForCorrectAnswer(userChoice)){
userChoice = getAnswer();
}
}
private static boolean checkForCorrectAnswer(char userChoice){
switch(userChoice)
{
case 'a':
case 'A':
System.out.println("Incorrect! 'Switch' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
return true;
case 'b':
case 'B':
System.out.println("Correct!");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
return true;
case 'c':
case 'C':
System.out.println("Incorrect! 'Float' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
return true;
case 'd':
case 'D':
System.out.println("Incorrect! 'True' IS a key word. The correct answer was B. ");
System.out.println("The program will now end. Thanks for answering!");
System.exit(0);
return true;
default:
System.out.println("Invalid character.");
// Repeats the getAnswer method to retrieve a valid character.
return false;
}
}
}
To avoid having to use the case expression to verify if it is lowercase or uppercase, I recommend that you use the following:
String value = String.valueOf(userChoice).toUpperCase();
This helps to make the conversion of lowercase to uppercase before doing the evaluation in the switch case.

java currency calculator pausing swtich to give output back to user

first question:
There is a do while loop, within the do section there is a switch. After selection case 1, some calculations are done, two options can result as shown in the If statement. My problem is code runs until the break; then just goes straight back to the menu loop. My question: how do i get the program to print the output for the user, then continue the menu loop?
Second question:
In case 1 there are two resulting options, the first being a failed response. from here, how do i get the program to loop back to the start of case 1 to ask for user input again? Even back to the main menu would be fine.
public static void showMenu() {
System.out.print('\u000c');
System.out.println("1 - Compute Change \n");
System.out.println("2 - Estimate Feast \n");
System.out.println("3 - \n");
System.out.println("4 - \n");
System.out.println("5 - I'm broke, get me out of here\n");
System.out.println("Select Option:\n");
}
public StackPost() {
System.out.println("Welcome to the Bank of Winterfell");
Scanner in = new Scanner(System.in);
do {
showMenu();
selection = in.nextInt();
switch (selection) {
case 1:
// get input, compute then decision:
if (something<somethingElse) {
// false response -
} else {
// correct response - system prints out some stuff back to user, back to main
// menu loop
}
break;
case 2:
break;
case 5:
System.out.println("\nEnding Now\n");
System.exit(0);
break;
default:
System.out.println("Instruction is invalid");
}
} while (selection != 5);
}
You could print "Press enter to continue" (or whatever you want to give notice of before locking the program), and add a call to Scanner#nextLine() before your break. This will lock the progression 'till user presses enter.
case 2:
// Some code here...
// Done, now show result and tell user to press any key to continue
System.out.println("Some fancy result from case handle code");
System.out.println("Press enter to continue...");
in.nextLine();
break;
You could add a while-loop that won't let the code continue 'till whatever input is expected in the first case is acceptable.
case 1:
System.out.println("Some handle that tells user to input something, and what is acceptable");
String input = null;
while(!(input = in.nextLine()).equals("something")) {
System.out.println("Wrong input, try again...");
}
// Input is acceptable, now do something with it...
System.out.println(input);
System.out.println("Press enter to continue...");
in.nextLine();
break;
Be aware, in your code, you call Scanner#nextInt(), and #nextInt doesn't consume the \n from pressing enter, and will thus be transferred into the switch case's usage of #nextLine(). You could avoid this with selection = Integer.parseInt(in.nextLine()).
You can use achieve it by:
For First question: Using return statement in case of correct response.
For Second question: Using while loop in case 1
After implementaing the proposed solution the StackPost() method will look like following. You can see the complete working code here:
public static void StackPost()
{
System.out.println("Welcome to the Bank of Winterfell");
try(Scanner in = new Scanner(System.in))
{
int selection;
do
{
showMenu();
selection = in.nextInt();
switch (selection)
{
case 1:
// get input, compute then decision:
while(true)
{
int something = in.nextInt();
int somethingElse = in.nextInt();
if (!(something<somethingElse)) {
// correct response - system prints out some stuff back to user, back to main
System.out.println("Print here the result");
// menu loop
return;
}
// false response - continue for next iteration in while-loop
}
//No need of 'break;' here
case 2:
break;
case 5:
System.out.println("\nEnding Now\n");
System.exit(0);
default:
System.out.println("Instruction is invalid");
}
} while (selection != 5);
}
}
Note: It is best practice to use try-with-resources while handling system resources which implements AutoCloseable interface.

Magic 8-ball program

I have an assignment for my Java class to program a Magic 8-ball. It is supposed to generate a random number for the response, contain a "while(true)" statement, and a switch statement for the replies. This is what I have so far. I can't seem to figure out how to work the "while(true)" statement in without it repeating infinitely.
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String question;
int retry;
int q1;
System.out.print("What is your question for the Magic 8-bit 8-ball? ");
question = input.next();
System.out.print(process());
/*This is where I am having the problem. How do I work a "while(true)" in
* to where this won't infinitely repeat?
*/
}
public static int process() {
Random rand1 = new Random();
int random = rand1.nextInt(9);
int ans = random;
switch (ans) {
default: System.out.println("Does not compute!! Error! Error!");break;
case 1: System.out.println("The answer is.............. 42");break;
case 2: System.out.println("To get to the other side!!!");break;
case 3: System.out.println("Out of memory! Try again!");break;
case 4: System.out.println("Who do you think I am, IBM's Watson?");break;
case 5: System.out.println("Danger Will Robinson!! Danger!!");break;
case 6: System.out.println("What do you think?");break;
case 7: System.out.println("Fatal error.....nahhh just kidding");break;
case 8: System.out.println("Well, this is fun....NOT!");break;
case 9: System.out.println("Um...... 1,000,000,000,000,000,000,000?");break;
}
return ans;
}
}
Hum, the point of a while (true) loop is to be infinite, unless you add a break statement in it.
while (true) {
doStuff();
// if someCondition is true, this will exit the loop
if (someCondition)
break;
}
Note that this is equivalent to
do {
doStuff();
} while (!someCondition);
or
boolean someCondition = false;
while (!someCondition) {
doStuff();
}
It is usually preferrable to not have an infinite loop (while (true) for example) and have an explicit condition instead. Some exceptions exist, for example if the condition is complicated to express or if you want to break the loop at a particular position of the loop and not at the beginning or at the end :
while (true) {
doStuff();
if (someCondition)
break;
doSomeOtherStuff();
}
One of the many possible ways:
Create a a char and assign it to 'Y' (i.e. char continueLoop = 'Y').
Use this to control the while statement (i.e. while(char == 'Y') ).
Ask the user for input and process the input (i.e. System.out.println("Continue? Y/N") and then use Scanner to read the input and assign it to continueLoop.
You can create something similar using booleans.

Repeating to the main menu upon a specific user input

I am trying to create a simple program in java where the user can input some lines and then save it and then load the data from the saved file.
Currently, i have the basic outline of the program, but am stuck on the first stage where the user enters his data, then wishes to return to the main menu for another selection.
Code:
import java.io.*;
import java.util.*;
public class Datafile{
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\Kence\\workspace\\Java 8 - Beyond the Basics - Working Files\\Practice Programs\\src\\Practice Data Edited",true));
String data = null;
String dataEntered = null;
int menuChoice = printMenu();
switch(menuChoice){
case 1:
System.out.println("Please enter a line of data");
dataEntered = input.nextLine();
if(Integer.parseInt(dataEntered) == 0){
System.out.println("OK");
//printMenu(); <--- Qn 1. Where i am stuck
return;
}else{
System.out.println(dataEntered);
}
//Why this does not recognize "quit" when entered
/*if(dataEntered == "quit"){ <--- Qn2. Where i am stuck
System.out.println("OK");
}else{
System.out.println("Error");
}*/
data += dataEntered;
System.out.println("Data entered.Please enter the next line of data or press quit to exit back to the main menu.");
break;
case 2:
System.out.println("2 Entered");
break;
case 3:
System.out.println("3 Entered");
break;
case 4:
System.out.println("4 Entered");
break;
}
input.close();
}
public static void printStars(){
for(int i = 0; i<66 ; i++){
System.out.print("*");
}
System.out.println();
}
public static int printMenu(){
printStars();
System.out.println("System Started");
printStars();
System.out.println("Enter 1 to input a new line of data");
System.out.println("Enter 2 to list all data");
System.out.println("Enter 3 to save existing data");
System.out.println("Enter 4 to load data");
printStars();
return Integer.parseInt(input.nextLine());
}
}
QN 1
In the code example above, when the user enters 0, the i can run printMenu(), but am unable to take any further action after that. I would like to be able to select the options 2,3 or 4 after the user enters 0.
Edit: printMenu works fine on the initial start-up, it's after i enter 1,input data, then press 0, that the new printMenu() does not work as i'm not actually testing the input with a switch statement. I can't figure out a way to run printMenu() again at this point without nesting another switch statement, and another switch statement after that and so on..
Qn2.
When i enter quit, the program does not output "OK", but outputs ERROR instead. I don't understand why this is happening as i am comparing the input (which is a string) with the string "quit", yet somehow the program does not recognise both strings as equals?
I would appreciate any clarifications and advice.
Thanks!
Qn1: Here's another way to retrieve the input, hopefully it will solve the problem:
public static int printMenu(){
...
intInput = input.nextInt();
input.nextLine();
return intInput;
}
Qn2: The == comparator is not used for strings. Try this instead:
if(dataEntered.equalsIgnoreCase("quit")) {
...
}

Java use user input to determine enum value

I'm currently hardcoding an enum value, which is running through a switch statement. Is it possible to determine the enum based on user input.
Choice month = Choice.D;
Instead of hardcoding the value D, can I use the user input here?
package partyAffil;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class partyAffil {
public static void main(String[] args) {
System.out.println("Choose from the following menu");
System.out.println("D, R, or I");
String choice = getInput("please choose a letter.");
Choice month = Choice.D;
switch(month){
case D:
System.out.println("You get a Democratic Donkey");
break;
case R:
System.out.println("You get a Republican Elephant");
break;
case I:
System.out.println("You get an Independent Person");
break;
default:
System.out.println("You get a unicorn");
break;
}
}
public enum Choice{
D, R, I;
}
private static String getInput(String prompt)
{
BufferedReader stdin = new BufferedReader(
new InputStreamReader(System.in));
System.out.print(prompt);
System.out.flush();
try{
return stdin.readLine();
} catch (Exception e){
return "Error: " + e.getMessage();
}
}
}
Each enum constant have its own name as declared in its declaration. Static method valueOf of particular enum returns the enum constant of this type by name.
Thus, instead:
Choice month = Choice.D;
just use this:
Choice month = Choice.valueOf(choice);
What if you create the switch on the input rather than the month (or both, if they must be implemented separately)?:
Choice month;
switch(choice.toUpperCase()){
case 'D':
month = Choice.D
System.out.println("You get a Democratic Donkey");
break;
...
}
Better yet, I believe you could even set the character values in the enum:
public enum Choice{
D('D'), R('R'), I('I');
}
This way, instead of case 'D': you can still use case D:
(Not sure about that one, I am more used to C-based languages)
Above given answers might help.
If you are not an expert, use following code that will you understand the steps.
public void run() throws Exception
{
switch (menu() ) //calling a menu method to get user input.
{
case 1:
//fyi, make sure you have all the methods in your code that is given for each menu choice.
//you can have print statement in your method.
// e.g. System.out.println("You get a Democratic Donkey");
method1();
break;
case 2:
method2();
break;
case 3:
method3();
break;
case 0:
return;
//following default clause executes in case invalid input is received.
default:
System.out.println ( "Unrecognized option" );
break;
}
}
private int menu()
{
//list of menu items.
System.out.println ("1. insert appropriate description for your menu choice 1.");
System.out.println ("2. ");
System.out.println ("3. ");
System.out.println ("4. ");
return IO_Support.getInteger(">> Select Option: ", "Unrecognized option"); //you can use scanner to get user input. I have user separate class IO_Support that has getInteger methods to validate int user input. the text "unrecognized option" is what the message that i want to print if the option is integer but not valid choice.
}

Categories

Resources