Switch returning same statement multiple times - java

I'm making a school assignment and this time around I thought about using a switch statement since it looked more efficient.
It's just something basic but if I enter a letter for example and after that number 1 for example it would return case 1 twice?
This is my code for the entire class so far:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
private int option;
public static void main(String[] args) {
Test t = new Test();
t.start();
t.optionMenu();
}
public void start() {
System.out.println("Make your choice:");
System.out.println("1: Play");
System.out.println("2: Options");
System.out.println("3: Exit");
}
public void optionMenu() {
try {
Scanner sc = new Scanner(System.in);
this.option = sc.nextInt();
System.out.println(this.option);
} catch (InputMismatchException e) {
System.out.println("Please enter a number");
optionMenu();
}
switch (this.option) {
case 1:
System.out.println("Game starting...");
break;
case 2:
System.out.println("Loading options");
break;
case 3:
System.out.println("Game exiting...");
System.exit(0);
break;
default:
System.out.println("Enter a valid number (1, 2 or 3");
break;
}
}
}
Any help would be much appreciated, thanks!

When you call sc.nextInt() without first asking if (sc.hasNextInt()), you are open to some strange behavior when end-users start typing unexpected input, such as letters. In this case the scanner would not advance its reading pointer, so your program will get stuck reading the same incorrect output.
To fix this issue, add a loop that "clears out" the invalid entry before attempting to read an int again, like this:
while (!sc.hasNextInt()) {
System.out.print("You need to enter an integer.");
sc.nextLine(); // Clear out the bad input
}
int val = sc.nextInt(); // At this point we know that sc.hasNextInt(), because that's the loop condition
Another point is that it is not a good idea to do with recursion what can be done with iteration: the recursive call to optionsMenu is going to accumulate as many levels of invocation as the number of times the end-user enters an incorrect value, so a very persistent user could theoretically force a stack overflow on your program by entering invalid data repeatedly.
Using the code fragment above would free you from the need to call optionsMenu recursively, and also from catching the input exception.

It's just something basic but if I enter a letter for example and after that number 1 for example it would return case 1 twice?
I'm not sure what you mean here. Firstly, your idea works, this code should be fine!
Second, if you enter anything besides just the number 1, 2, or 3, you will go to the "default:" block of code. Since you are prompting the user again if they fail, typing "a" or "a1" into the prompt just shows the menu again. The user needs to just type "1", "2", or "3" to successfully select a menu option.

Related

How to stop a user from entering a letter in a switch case when the letter is the first input entered

When using a switch case with integers, I am able to successfully stop the user from crashing the program with a try/catch when they enter a letter (a, b, c, etc, not case specific). However, I can only stop it after an integer is entered. For this example, it is NOT my actual code, it is only an example as it is a general question. Secondly, I want to try and get it working with suggestions, not having it done for me:
int choice
Scanner scan = new Scanner (System.in);
System.out.println ("Enter a number");
System.out.println ("1: Example one");
System.out.println ("2: Example two");
System.out.println ("0: Exit");
choice = scan.nextInt();
Loop: for (;;)
{
switch (choice)
case 1: System.out.println ("Example one successful");
choice = scan.nextInt();
break;
case 2: System.out.println ("Example two successful");
choice = scan.nextInt();
break;
case 0: System.exit (0);
break Loop;
default: try
{
System.out.println ("Please enter a number")
choice = scan.nextInt();
}
catch (InputMismatchException error)
{
System.out.println ("Not a valid number: " + error);
choice = scan.nextInt();
}
If the user enters a "1", it outputs the proper text inside the case 1 block. The same goes for case 2 and case 0 to exit. It will loop properly and continuously like this:
Enter a number: 1
Example one successful
Enter a number: 1
Example one successful
Enter a number: 2
Example two successful
Enter a number: ghdrf
Not a valid number: java.util.InputMismatchException
Enter a number: 0
The try/catch works in catching the wrong input, all the other case work. The problem is if the user never enters an integer from the start and enters a letter instead. It will throw the InputMismatchException right away. The try/catch doesn't even try to catch it.
My thinking was because I assigned the scanner to read an integer from the start. I tried to start there. I originally tried this between the loop label and the switch statement as it is the only place I could put it to not get an error:
Loop: for (;;)
{
String letter = input.nextLine();
if(letter.matches("[1-9]*")
{
choice = Integer.valueOf(letter);
}
else
{
System.out.println("Invalid input");
}
switch (choice)
...
This worked somewhat in the same way as my try/catch except it was simply printing "invalid input" with each selection (because of my print statement, I know that). But the same problem was occurring. If a letter was input instead of an integer right off the bat, it would throw an InputMismatchException. I have a feeling it has something to do with what is in the scanner. I've tried experimenting with "next(), nextLine(), nextInt(), equals()" and I've tried parsing with "Integer.valueOf()" trying to get the current line in the scanner to check it or parse it.
This leads me to my questions:
Am I correct to assume that the scanner is reading the input and throwing the exception before I have a chance to catch it?
How do I read the first line in the scanner at the beginning of the program in order to check if it is an integer or a String? I'm not a big fan of skipping the first line because then it causes the user to have to input their number twice in order for the program to print out a message such as:
Enter a number: 1
Enter a number: 1
Example one successful
Any input is greatly appreciated, thank you!
Question #1: no. The problem is, that the exception occurs in those lines which are not surrounded by try-catch (e. g. before the loop, in case 1 or case 2).
Question #2: to read a line, use Scanner#nexLine(). There's no need to have the user to perform his input twice.
Hint: write a method that requests an int value from the user and that returns only, if he entered a correct value.
You have 2 calls to next int. You're only catching exceptions from one of them. You need to do it for both.
I'd put some thought into reorganizing this code a bit. You don't really need two calls to nextInt. You can do it with one by changing what things are in the loop and what aren't. Since you're a beginner I'll let you think about that for a bit rather than hand you the answer.

User input and Exception in Java

I want to add an integer to a list based on user input. The user has to type all the integers he/she wishes then press enter. if they finish inputting integer, they are supposed to press the "enter" button without typing anything.
I have made my code, but there are several mistakes
the exception keeps popping up because every time say for example I enter integer 10, then I finish. I press "enter" with nothing. this raises the exception. how do I tackle this problem?
and another thing, how do I make the program so that if the user puts invalid input, instead of crashing or breaking. It asks the user again to prompt the correct input.
this is what I have done
package basic.functions;
import java.util.*;
import java.text.DecimalFormat;
public class Percent {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
reader.useDelimiter(System.getProperty("line.separator"));
List<Integer> list = new ArrayList<>();
System.out.println("Enter Integer: ");
while (true) {
try {
int n = reader.nextInt();
list.add(Integer.valueOf(n));
} catch (InputMismatchException exception) {
System.out.println("Not an integer, please try again");
break;
}
}
reader.close();
}
}
output
Enter Integer:
10
Not an integer, please try again
[10]
I'd suggest you utilise Scanner#hasNextInt to identify whether an integer has been entered or not. As for when the "user presses enter without typing anything", we can simply use the String#isEmpty method.
while (true) {
if(reader.hasNextInt()) list.add(reader.nextInt());
else if(reader.hasNext() && reader.next().isEmpty()) break;
else System.out.println("please enter an integer value");
}
note - in this case, you don't need to catch InputMismatchException because it won't be thrown.
while (true) is generally a bad sign, if you ever have that in your code you are almost certainly wrong.
What you probably want is something like this:
String input;
do {
input = reader.next();
// Parse the input to an integer using Integer.valueOf()
// Add it to the list if it succeeds
// You will need your try/catch etc here
while (!input.isEmpty());
Here the loop is checking the exit condition and running until it meets it. Your processing is still done inside the loop as normal but the program flow is a lot cleaner.

How to ask te user and depending on his response run all the code again?

I'm a newbie in Java. I started these days and I'm practicing the catch and try exception. I have this code below which solve an operation between to numbers and I'd like to know what can I do, if for example I want that the user, once he makes an operation and get his result, that this has the possibility to make another operation. something like comes up a question asking if he wants to realize another problem and the code run again from the beginning.
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
int x=1;
while(x==1){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
x=2;
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
You can do, for example, adding an if statement with a
System.out.println("Do you want to recalculate ? (1/0 Yes/No)");
Operation.nextInt();
then if the input is 1, keep x = 1, else do x = 2.
Try this code amendment;
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
//better practice
while(true){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
System.out.println("Continue? (y/n)");
String response = Operation.nextLine();
if (response.equals("n")){
break;
}
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
To allow your user to calculate division again, you could use a do-while loop. With this loop you can execute the code inside once, ask the user if they would like to calculate again, and repeat the code if they do.
An outline of your code with the loop would something like this:
...
boolean again = true;
do { //Main loop
try {
... //Your division code
... //Put code to ask the user if they want to calculate again here
} catch(Exception e) {
...
}
} while(again == true); //Repeat if the user wants to continue
To get input on if the user wants to calculate again, I recommend using another do-while loop with your Scanner. This loop will allow you to repeat the code when the answer is invalid. In this case, when it's not "y" or "n".
String input;
do {
System.out.println("Would you like to continue? (y/n)");
input = operation.next();
} while(!input.equalsIgnoreCase("y") && !input.equalsIgnoreCase("n"));
After you have got the user's input, you still need to terminate the loop if they said "n". To do this you could use an if statement.
if(input.equalsIgnoreCase("n")) {
again = false; //Terminate the main loop
operation.close(); //Prevent any resource leaks with your Scanner
}
There is no need to check if the user input "y" as again is set to true by default.
Side Note: Variables should always be camelCase. Look at the Java Naming Conventions to learn more about naming things in Java.
EDIT:
The reason the console is repeatedly logging that you entered a non-number even though you entered it once, I'm not exactly sure. I think it's because the call to nextInt() never finishes because of the InputMismatchException being thrown, causing the next call to nextInt() (After the do-while repeats) to think that the letter/symbol you just entered is the one you want to process, repeating the exception over and over again.
To solve this, add this line into your catch block:
if(operation.hasNext()) operation.next();
This will call next() and complete the process of marking the letter/symbol you just entered as already processed, then repeat the do-while loop as normal.

Trouble returning to command options using loops/ only one command is being run (JAVA)

This is my first time on this site. I am taking a course in Java right now and I am having some trouble with this code/program that I am supposed to make that allows the user to select whether they want to see "good monkeys", "bad monkeys" or "show monkeys". It is nowhere near done but I am having trouble returning to the command screen/area after a command is completed. I would like the commands to be used as many times as possible. Secondly, my program treats every input if someone put in "Good Monkey". So if you put in a word like "pineapple", it will still greet you with the output designated for the "Good Monkeys" input.
I've looked online and seen that maybe I should use a "do-while" loop and use "switch". Any input/ help would be greatly appreciated. Thank you so much!
Here is my code: public class and public static and Scanner import are in this code, but for some reason I cannot add them into this post without messing up the formatting of the code.
Scanner jScanner = new Scanner(System.in);
System.out.println("please enter Good Monkeys, Bad Monkeys or Show Monkeys");
String userChoice = jScanner.nextLine();
for (int b= 1; b < 11000; b++)
{
if (userChoice.equalsIgnoreCase("Good Monkeys"));
{
System.out.println("You have selected Good Monkeys");
System.out.println("How many monkeys do you want? Put in a integer between 3 and 20");
Scanner goodMonkeyScanner = new Scanner (System.in);
int userChoiceGood = goodMonkeyScanner.nextInt();
if (userChoiceGood >= 3 && userChoiceGood <= 20)
{
System.out.println("Here you go");
System.out.println("Monkeys (metapohorical)");
break;
}
else if (userChoice.equalsIgnoreCase("Bad Monkeys"))
{
System.out.println("You have selected Bad Monkeys");
System.out.println("How many monkeys do you want? Put in a integer between 3 and 20");
Scanner badMonkeyScanner = new Scanner (System.in);
int userChoiceBad = badMonkeyScanner.nextInt();
if (userChoiceBad >= 3 && userChoiceBad <= 20)
{
System.out.println("Here you go");
System.out.println("Monkeys (metapohorical)");
break;
}
else
System.out.println("Sorry this doesn't work");
}
else if ((userChoice.equalsIgnoreCase("Show Monkeys")))
{
System.out.println("Monkeys");
System.out.println("0");
System.out.println("\\/");
System.out.println(" |");
System.out.println("/\\");
break;
}
else
{
System.out.println(" Wrong Answer. Try again");
}
break;
}
}
}
}
First, you need to define the loop. Second, you need to put the input instruction inside the loop.
I'll include a done variable to detect when the user wants to escape
So, let's code:
Scanner jScanner = new Scanner(System.in);
boolean done = false;
while(!done) {
System.out.println("please enter Good Monkeys, Bad Monkeys or Show Monkeys");
System.out.println("(or enter 'done' to exit");
String userChoice = jScanner.nextLine();
swithc(userChoice.toLowerCase()) {
case "good monkeys":
/*
* The code for this option
*/
break;
case "bad monkeys":
/*
* The code for this option
*/
break;
case "show monkeys":
/*
* The code for this option
*/
break;
case "done":
done = true;
break;
default:
System.out.println("Your input isn't what I expected!\nTry again!");
break;
}
}
The code, explained:
That while(!done) stuff can be read as "while 'not done' do what follows"
userChoice.toLowerCase(): I convert the userChoice to lower-case, to simplify comparissons. That way, I only need to compare the string with other lower-case strings
switch(userChoice.toLowerCase()): ... hmmm... I think you can figure it out yourself ;)
That default block is what happens if no other case is valid
The "done" block will set the done variable to true, and thus it will terminate the loop
Important: ALWAYS end the case blocks with break
Further reading:
The Java Tutorials: Language basics
The while and do-while statements
The switch statement
Also, I recommend you study Flowcharts and, before start coding, try to draw in paper a flowchart of your program. That way, you will have a clear image of your program before you start writing the very first line of code.

break to lable as default case in switch statment not behaving logically

First thank you for reading. Also I'm very aware of how I can get this to work they way I want it to. I'm just experimenting and not getting expected results.
When I run this code I would expect that when I enter the letter X I would be asked
to try again and re-attempt to enter the letter B. Well, I am. However The program will then break to the start: label and process based on the new value of input we got in the
default case. If on my second attempt I enter the letter B, nothing gets executed in the
switch statement. If you enter the letter B on your second try, the program will print that you entered B and then the program will terminate. Why is this?
import java.util.Scanner;
public class Help
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
System.out.println("Enter the letter B: ");
char input = kb.nextLine().charAt(0);
start:
switch(input)
{
case 'B':
System.out.println("Nice Work!");
break;
default:
System.out.println("Try again: ");
input = kb.nextLine().charAt(0);
System.out.println(input);
break start;
}
}
}
The labeled break statement is meant for terminating loops or the switch statement that are labeled with the corresponding label. It does not transfer control back to the label. Your switch statement is simply falling through to the end of program, as it should.
A labeled break would only be helpful if you had nested switch statements and needed to break out of the outer one from the inner one.
See this for further information.
Use while cycle:
import java.util.Scanner;
public class Help
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
System.out.println("Enter the letter B: ");
while(true)
{
char input = kb.nextLine().charAt(0);
switch(input)
{
case 'B':
System.out.println("Nice Work!");
break;
default:
System.out.println("Try again: ");
}
}
}
}

Categories