Continue Program Execution after Catching Exception - java

After catching an exception, how do I continue the execution of a Java program?
I made a program that asks a user to enter a number and it will return that number divided by a random number generated. However, if the user enters a letter like 'a', an exception will be caught.
How do I make the program continue its execution instead of terminating after it catches the exception?
do{ //Begin of loop
try{ //Try this code
System.out.println("Enter a number");
double i = read.nextDouble(); //Reads user input
double rn = r.nextInt(10); //Generates random number rn
System.out.println(i + " divided by random number " + rn + " is " + (i/rn));
}catch(InputMismatchException type_error){ //Catches error if there is a type mismatch
//Example error: if user enters a letter instead of a double
System.out.println("Error. You cannot divide a letter by a number!");
break; //break stops the execution of the program
}
//using a continue statement here does not work
}while(true); //Loop forever

Continue won't help! If you use Scanner class to input the numbers, you got an infinite loop writing "Error. You cannot divide a letter by a number!" to the output.
Your code waits for a double number, but got a letter. This event triggers an exception, the code displays the error message. But the letter will remains in the scanner, so the nextInt command tries to load the same letter in the next iteration, without wait for you typing.
In the catch block, you have to empty the scanner with a read.next() command.
Scanner read = new Scanner(System.in);
Random r = new Random();
do { //Begin of loop
try { //Try this code
System.out.println("Enter a number");
double i = read.nextDouble(); //Reads user input
double rn = r.nextInt(10); //Generates random number rn
System.out.println(i + " divided by random number " + rn + " is " + (i / rn));
} catch (InputMismatchException type_error) { //Catches error if there is a type mismatch
//Example error: if user enters a letter instead of a double
System.out.println("Error. You cannot divide a letter by a number!");
// Empty the scanner before the next iteration:
read.next();
}
//using a continue statement here does not work
} while (true); //Loop forever

The continue statement will restart the loop (as opposed to the break statement, which terminates the loop).
As such if you replace break; with continue;, you will keep on looping after your Exception is caught (providing no other Exception is thrown but the one caught), ans the error message is displayed.
Essentially it will print "Enter a number" again, etc.
Warning
You also need to consume the Scanner's next value.
If you don't, using continue will loop forever with no user interaction when an error occurs.
Example
Scanner read = new Scanner(System.in);
do {
try {
// trimmed out non-necessary stuff
System.out.println("Enter a number");
double i = Double.parseDouble(read.nextLine());
System.out.println(i);
// changed exception caught
}
catch (NumberFormatException type_error) {
System.out.println("Error. You cannot divide a letter by a number!");
continue;
}
} while (true);
Final note
As mentioned by Berger, continue here is not even necessary because you are only printing a warning message.

The break statement is causing the end of the loop.
The break statement has two forms: labeled and unlabeled. You saw the
unlabeled form in the previous discussion of the switch statement. You
can also use an unlabeled break to terminate a for, while, or do-while
loop
Solution :
Change it to continue.
The continue statement skips the current iteration of a for, while ,
or do-while loop.

The break statement causes the loop to exit. Since you have no code in the loop after the try-catch construct, you can simply remove the break statement.
Note that the Scanner method (I assume read is a Scanner) nextDouble() returns the double value if the next token represents a double. If not, it throws an exception without consuming that token. So you need to ensure you consume the next value, which you can do with read.next():
do{ //Begin loop
try{ //Try this code
System.out.println("Enter a number");
double i = read.nextDouble(); //Reads user input
double rn = r.nextInt(10); //Generates random number rn
System.out.println(i + " divided by random number " + rn + " is " + (i/rn));
}catch(InputMismatchException type_error){ //Catches error if there is a type mismatch
//Example error: if user enters a letter instead of a double
System.out.println("Error. You cannot divide " + read.next() + " by a number!");
}
} while(true);

One more solution is just replace break with read.nextLine();.
break statement is causing the end of the loop.
continue will prints Enter a number again and again.
But read.nextLine();, code will asks the input again and again.
If you remove read.nextLine(); or continue, code will prints Enter a number again and again.

Just remove the break; from there, and everything will work fine.
Remember however to put a termination condition, i don't see it anywhere.

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.

Java - Try/Catch not moving past InputMismatchException

This is my first Java program. The assignment is to create a program as follows:
Develop a Java program that works as follows:
1). When the program is started, it displays a message welcoming the player: "Welcome to Game Guru!"
2). Then it creates a secret random number between 1 and 20;
3), Then it displays a message saying: "Guess my magic number [1-20]: "
4). Read and check the number entered by the player.
If is not a number, the program displays a message saying: "Should enter a number". then go back to step 3)
If the number is out of range, the program displays a message saying: "Number out of range". Then go back to step 3)
If the number is smaller than the secret number, the program displays a message saying: "Number too small". Then go back to step 3)
If the number is greater than the secret number, the program displays a message saying: "Number too large". Then go back to step 3)
If the number is the same as the secret number, the program displays a message saying: "You got it!". Then go to step 5)
5). The program displays a message saying: "Want more games?"
6). Read the player's answer. If the answer is "yes", then to step 1); If the answer is "no", then go to step 7)
7). The program displays message "Thanks for playing the game. Goobye".
I have gotten it working completely EXCEPT when entering anything other than an INT it gives an exception. I tried researching this myself and found the Try/Catch but it doesn't seem to be working for me. My instructor wont help me...despite the fact that he hasn't actually taught any of this...
Here's my code:
public static void main(String[] args)
{
// TODO Auto-generated method stub
String more;
do
{
System.out.println("Welcome to Game Guru!");
int number = 1 + (int)(Math.random() * 20);
int guess = 0;
Scanner input = new Scanner(System.in);
try
{
System.out.println("Guess my magic number [1-20]: ");
guess = input.nextInt();
}
catch (Exception e)
{
System.out.println("Should enter an integer");
}
while (guess != number)
{
if (guess > 20 || guess < 1)
{
System.out.println("Number out of range");
System.out.println("Guess my magic number [1-20]: ");
guess = input.nextInt();
}
else if (guess < number)
{
System.out.println("Number too small");
System.out.println("Guess my magic number [1-20]: ");
guess = input.nextInt();
}
else if (guess > number)
{
System.out.println("Number too large");
System.out.println("Guess my magic number [1-20]: ");
guess = input.nextInt();
}
}
if (guess == number)
{
System.out.println("You got it!");
}
System.out.println("Want more games? Please enter Y or N.");
more = input.next();
} while (more.equals("y") || more.equals("Y"));
System.out.println("Thanks for playing the game. Goodbye");
}
}
Here's the console:
Welcome to Game Guru!
Guess my magic number [1-20]:
a
Should enter an integer
Number out of range
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Unknown Source)
at java.base/java.util.Scanner.next(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
Guess my magic number [1-20]:
at Game.main(Game.java:46)
I really appreciate any insight into this. I'm at my wits end...I should be paying Google my tuition.
So, starting with...
try
{
System.out.println("Guess my magic number [1-20]: ");
guess = input.nextInt();
}
catch (Exception e)
{
System.out.println("Should enter an integer");
}
Basically, if an exception occurs, the Scanner still contains non-numerical data in it's buffer, this means that if you then try and read the buffer again, doing something like...
guess = input.nextInt();
You will get the same exception again.
A general solution is to call input.nextLine() to clear the buffer before attempting to read new data from it. Personally, I'd use nextLine for all the inputs and Integer.parseInt to parse those elements which you want as int values, but that's me.
Since you have to ask the user for input each time they need to make a guess, you could simplify your solution by using a do-while loop instead (you have to enter the loop at least once any way), this way you could get the input, verify the value (as an int) and perform your required logic on it, all within a single basic loop...
Scanner input = new Scanner(System.in);
String more = "N";
do {
System.out.println("Welcome to Game Guru!");
int number = 1 + (int) (Math.random() * 20);
int guess = 0;
do {
try {
System.out.println("Guess my magic number [1-20]: ");
String text = input.nextLine();
guess = Integer.parseInt(text);
if (guess > 20 || guess < 1) {
System.out.println("Number out of range");
} else if (guess < number) {
System.out.println("Number too small");
} else if (guess > number) {
System.out.println("Number too large");
}
} catch (NumberFormatException e) {
System.out.println("Should enter an integer");
}
} while (guess != number);
System.out.println("You got it!");
System.out.println("Want more games? Please enter Y or N.");
more = input.nextLine();
} while (more.equalsIgnoreCase("y"));
In the try, you are giving the code you want to execute (fine). In the except statement, you are correctly printing out the error too (great).
Unfortunately, you didn't fix it!
It probably makes sense to put your try/catch in a while loop that repeats until you get valid input. That way, once it works, you move on to the rest of your logic which is dependent on getting valid input from the user in the try/catch.
You're asking to enter an int, if the user enter another value as a String or Float you will get an exception.
Add another try{} catch{} block to verify if it is an Integer otherwise cast it
What happens in your code is that it catches that exception in the first try/catch, prints System.out.println("Should enter an integer"); and then proceeds to the rest of the do block. You need to continue after printing that message.
However, you'll encounter more bugs in that code as you continue testing, this is just to answer your question about that exception.
The purpose of your try/ catch is to tell the user that the number they selected is not an integer. The program is not supposed to continue if you enter something other than an integer, as it says in step 4- The first if statement is used to verify that the number is an integer.
Instead, you are using a try/ catch, which also stops the program, but a little differently.try/catch block
The block of code in the try statement prompts the user to enter a number 1-20. If it is not, it throws the exception because the number entered is not an integer. It prints the message " Should enter an integer", and prints out the errors that should tell the user what is wrong. It is telling you there is an error in the Main class of your program, and where the problem is located. The purpose of the print statement " Should enter an integer" was to prompt the user to enter an integer the next time the program runs, so the program can then run correctly.
In your case, the if statement would make more sense to use. Again, the only point of this block of code is to verify the user has entered an integer.

Why am I getting this weird bug with only a type error and not a zeroDivision error?

So I really have 2 questions. The 1st is, in Java how do I do the equivalent of this python code:
while True:
try:
num1 = int(input('Enter num1: '))
num2 = int(input('Enter num2: '))
print(str(num1) + ' / ' + str(num2) + ' = ' + str(num1 / num2))
break
except:
print('ERROR')
What I want is the program to say to the user "No you did this wrong! Now do it again until you get it right." I tried writing this in java:
import java.util.Scanner;
public class TryCatch {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (true) {
try {
System.out.print("Enter num1: ");
int num1 = input.nextInt();
System.out.print("Enter num2: ");
int num2 = input.nextInt();
System.out.println(num1 + " / " + num2 + " = " + num1 / num2);
break;
} catch (Exception e) {
System.out.println(e);
System.out.println(e.getCause());
System.out.println(e.getMessage());
}
}
}
}
Now this does exactly what I want it too when num2 is equal to 0. For reference, here's the output when that happens and I kill the process after the 1st iteration:
Enter num1: 5
Enter num2: 0
java.lang.ArithmeticException: / by zero
null
/ by zero
Enter num1:
Process finished with exit code 1
However when either num1 or num2 is a String, java prints the following 3 lines in an infinite loop until I kill the process:
java.util.InputMismatchException
null
null
This obviously means that I'm doing something wrong, but for the life of me I don't know why the catch block keeps running in an infinite loop with a type error but not with zeroDivision error...
So my 2 specific questions are:
How do I achieve what I've described that I want to do? i.e. make the program tell the user "No you did this wrong! Now do it again until you get it right."
What is the reason that this is an incorrect solution? i.e. why does the catch block run in an infinite loop when there's a type error but not a zeroDivision error?
EDIT:
Since I can only accept 1 answer, I wanted to specifically thank #rgettman for explaining how the nextInt() method causes my particular problem and #Alireza Dastyar for giving me what I think is a more elegant solution since it changes where the exception is thrown from instead of sort of cleaning up the messy input after the fact which means that you have give dummy input when that particular exception isn't thrown.
The execution never gets to the division by zero. When you type in something that nextInt() can't handle, that method throws an InputMismatchException before the execution reaches the division expression.
Also, when a Scanner method that consumes input throws that exception, it doesn't consume the offending input, the loop repeats, and nextInt() throws an exception on the same input, causing the infinite loop.
The nextInt() javadocs:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
In the catch block, print the message to the user to try again.
Call input.next() in the catch block to consume the incorrect input and advance to the next token.
You will need to carefully handle the input when the incorrect input is the first input; there may be 2 tokens of input to skip in this case.
Consider calling hasNextInt() to determine if there is an integer to be parsed on the input.

"hasNextInt" does not detect subsequent input; where to put "nextLine"?

I am brand new at Java and this one is throwing me. Using the below code it loops through for the first question until I enter anything but an integer but after finishing that loop it does not stop for the remaining question.
Through a bit of research and reading I have found that I need to use the in.nextLine() to eat the newline character after the input. However no matter where I place the nextLine() it doesn't work? I thought it would be after the first int input = in.nextInt(); line but that did not work. Any help on where it would go and why?
System.out.print("How many CUs per course are remaining in your degree program? Enter any letter to quit: ");
while (in.hasNextInt()) { // Verify input is an integer
int input = in.nextInt();
if (input <= 0) // Verify that input is not negative or zero
{
System.out.println("Please enter a positive number or any letter to quit");
System.out.print("Add another course or any letter to quit: ");
} else {
courseCuList.add(input);
System.out.print("Add another course or any letter to quit: ");
}
}
System.out.print("How many CUs do you plan to take per term?");
while (in.hasNextInt()) {
int input = in.nextInt();
// in.nextLine(); This line consumes the \n
if (input <= 0) {
System.out.println("Please enter a whole positive number.");
System.out.println("How many CUs do you plan to take per term?");
} else {
cuPerTerm = in.nextInt();
}
}
Your problem is that in while (in.hasNextInt()) each call of hasNextInt needs to wait for user input, and then test if it is integer or not.
So each time user give integer, condition will be evaluated to ture, loop will execute and condition will need to be checked again, and if it is integer loop will execute again. This will go again and again until hasNextInt will be able to return false, for instance when user will give non-integer - like letter. But in this case condition in next loop will also return false because this non-integer value was not consumed after first loop. To let second loop work you would need to invoke nextLine two times
to consume line separator after previously put correct integer
to consume actual non-integer value
But this may also fail if user will not put any integer before non-integer value because there will be no line separator to consume.
So consider changing your logic to something similar to
boolean iterateAgain = true;
System.out.print("give me positive number: ");
while (iterateAgain) {
// this inner loop will move on only after getting integer
while (!in.hasNextInt()) {//here program waits for user input
in.nextLine();// consume non-integer values
System.out.print("that wasn't positive number, try again: ");
}
int number = in.nextInt();// now there must be number here
in.nextLine();// consume line separator
if (number > 0) {
System.out.println("you gave " + number);
// do what you want with this number
iterateAgain = false;// we can leave loop
} else
System.out.print("that wasn't positive number, try again: ");
}
If you want to execute next loop then all you need is reset iterateAgain value to true.
You need to read twice.
The exit condition on your while loop is hasNextInt() - checking to see if the next token is an integer doesn't actually clear that token, which means that the next nextLine() is going to read the token, and the subsequent nextLine() will read the newline character.
To demonstrate this, place the following between the loops:
System.out.println(in.nextLine() + " | " + in.nextLine());
For the input 4, 4, A, you will see the output:
How many CUs per course are remaining in your degree program? Enter any letter to quit: 4
Add another course or any letter to quit: 4
Add another course or any letter to quit: A
| A
How many CUs do you plan to take per term?
There are two tokens that need to be cleared from the buffer, and neither of them are integers. Because of this, no matter where you put nextLine(), it will fail - you need to insert it twice. If you only insert it once, the next token won't be an integer, and hasNextInt() will fail when the program tries to enter the second loop.
In order to get your program to work, simply insert:
in.nextLine(); in.nextLine();
before the second loop. (Note that you shouldn't put both this and the print-out in, as this will read four times.)

my codes goes infinity loop and does not prompts the user anymore

boolean acceptPcode=true;
boolean acceptQty=false;
int Qty=0;
List<Integer> purchasedProdQty=new ArrayList<>();
while(acceptPcode==true && acceptQty==false){
do{
try{
System.out.print("Enter Qty: ");
Qty=sc.nextInt();
acceptQty=true;
}catch(InputMismatchException ime){
System.out.println("Invalid quantity please enter a number!");
acceptQty=false;
}
if(acceptQty==true)
purchaseProdQty.add(Qty);
}while(acceptQty==false);
}
my question is that when i enter a letter it goes in an infinity loop and it doesn't prompt the user to enter a quantity ....which is
Enter Qty: Invalid quantity please enter a number!
Enter Qty: Invalid quantity please enter a number!
Enter Qty: Invalid quantity please enter a number!......
You forgot to read the \n (or \r\n) characters that are from the next line. In your current code, the scanner is waiting for an int input, bu the current next input is this break line char. Just add sc.nextLine() in your code to consume the break line char:
Qty=sc.nextInt();
sc.nextLine();
acceptQty=true;
From what I can gather it seems your scanner(sc) is throwing an exception. This causes acceptQty to constantly be false keeping you stuck in your inner do-while loop.
You need to consume any illegal characters in the exception block otherwise they won't be consumed by the Scanner#nextInt method call causing the loop to repeat itself indefinitely:
} catch(InputMismatchException ime) {
System.out.println
("Invalid quantity: " + sc.nextLine() + " please enter a number ");
...
}
You are getting exception while reading out of sc and so it always go into infinity loop. Can you paste what's the value assiged in sc?
I believe you're doing this all wrong. Your method of validation is very obscure and can be simplified. Suppose you have the following method:
public int readNumber(final String prompt, final Scanner scanner){
System.out.println(prompt);
try{
return scanner.nextInt();
}catch(Exception ex){
System.err.println("Enter a valid number");
return readNumber(prompt, scanner);
}
}
This method will print out the prompt (the first argument) and read input from the provided Scanner (the second argument). If the user enters something that can't be parsed as an int, it will invoke the same method (recursion).
Take out both of your loops and when you want to read an int from your Scanner, do something like:
int value = readNumber("Enter a quantity", sc);
You know for sure that Integer.MAX_VALUE >= value >= Integer.MIN_VALUE

Categories