Resume loop after caught exception - java

I am catching an inputMismatchException in my main method and want my do-while loop to iterate again after the exception is caught. I even coded an explicit continue statement but that didn't work. How can I do so?
public class AddressBookApp {
public static void main(String[] args) {
AddressBook abook = new AddressBook();
System.out.println("Welcome to the Address Book Application\n");
Scanner sc = new Scanner(System.in);
int menuNumber = 4;
loop:
do {
abook.menu();
try{
menuNumber = sc.nextInt();
System.out.println();
if (menuNumber < 1 || menuNumber > 4){
System.out.println("Please enter a valid menu number\n");
} else if (menuNumber == 1) {
abook.printEntries();
} else if (menuNumber == 2) {
abook.addEntry();
} else if (menuNumber == 3) {
abook.removeEntry();
} else {
System.out.println("Thanks! Goodbye.");
sc.close();
return;
}
} catch (InputMismatchException ime) {
System.out.println("Please enter an integer");
sc.next();
continue loop;
}
} while (menuNumber != 4);
sc.close();
}
}

You left menuNumber equal to 4, which is the termination condition of your loop. Of course your loop will end.

You initialized menuNumber to 4, but do not change it in case of an exception. The loop does attempt to continue, but exits because the statement menuNumber != 4 is false.
int menuNumber = 4;
loop:
do {
abook.menu();
try{
menuNumber = sc.nextInt();
System.out.println();
if (menuNumber < 1 || menuNumber > 4){
System.out.println("Please enter a valid menu number\n");
} else if (menuNumber == 1) {
abook.printEntries();
} else if (menuNumber == 2) {
abook.addEntry();
} else if (menuNumber == 3) {
abook.removeEntry();
} else {
System.out.println("Thanks! Goodbye.");
sc.close();
return;
}
} catch (InputMismatchException ime) {
System.out.println("Please enter an integer");
sc.next();
continue loop;
}
} while (menuNumber != 4);

Try this
} catch (InputMismatchException ime) {
if (fatal(ime)) {
throw ime;
} else {
// try again
continue;
}

The loop doesn't continue because an exception of a type OTHER than InputMistmatchException is being thrown. Change the catch to:
catch (Exception e)
or at least add that all encompassing catch condition.
A better solution is to inspect exactly what exception is being thrown and why, and then fix the problem leading to the exception. Having an all encompassing catch with a continue statement could, in theory, lead to an infinite loop because menuNumber is not incremented.

Related

Try-Catch Exception Handling does not provide the correct response

I'm not sure why when I input anything other than an integer value, the output isn't showing Invalid Format!.
That's the exception handling that I'm trying to achieve. Also, how can I close the Scanner in a finally clause without causing an infinite loop.
class ConsoleInput {
public static int getValidatedInteger(int i, int j) {
Scanner scr = new Scanner(System.in);
int numInt = 0;
while (numInt < i || numInt > j) {
try {
System.out.print("Please input an integer between 4 and 19 inclusive: ");
numInt = scr.nextInt();
if (numInt < i || numInt > j) {
throw new Exception("Invalid Range!");
} else {
throw new InputMismatchException("Invalid Format!");
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
scr.next();
}
}
scr.close();
return numInt;
}
This is the output I'm trying to get:
If you enter anything other than an int the error will get thrown at the line:
numInt = scr.nextInt();
And then get caught in the catch block, thus skipping the print statement. You need to check if there is a next int:
if(!scr.hasNextInt()) {
throw new InputMismatchException("Invalid Format!");
}
Also, how can I close the Scanner in a finally clause without causing an infinite loop.
You do not need to close the Scanner in a finally block. In fact, you shouldn't close it at all. It is bad practice to close System.in. Generally if you did not open a resource, you should not close it.
You need to catch InputMismatchException in a separate catch block before Exception catch block and add scr.next(); like following:
public static int getValidatedInteger(int i, int j) {
Scanner scr = new Scanner(System.in);
int numInt = 0;
while (numInt < i || numInt > j) {
try {
System.out.print("Please input an integer between 4 and 19 inclusive: ");
numInt = scr.nextInt();
if (numInt < i || numInt > j) {
throw new Exception("Invalid Range!");
}
} catch (InputMismatchException ex) {
System.out.println("Invalid Format!");
scr.next();
} catch (Exception ex) {
System.out.println(ex.getMessage());
scr.next();
}
}
scr.close();
return numInt;
}
Below code will work for you,this is the another approach you can use to get your desire output.
In this code i have handled the InputMismatch in catch block.
public static int getValidatedInteger(int i, int j) {
Scanner scr = new Scanner(System.in);
int numInt = 0;
while (numInt < i || numInt > j) {
try {
System.out.print("Please input an integer between 4 and 19 inclusive: ");
numInt = scr.nextInt();
if (numInt < i || numInt > j) {
System.out.println("Incorrect Range!");
}
} catch (InputMismatchException ex) {
System.out.println("Incorrect format!");
scr.next();
}
}
scr.close();
return numInt;
}

Exception in do while loop

I have this piece of code:
do {
try {
input = sc.nextInt();
}
catch(Exception e) {
System.out.println("Wrong input");
sc.nextLine();
}
}
while (input < 1 || input > 4);
Right now, if I input 'abcd' instead of integer 1-4, it gives message "Wrong Input" and the program loops, how can I make it so that it also gives "Wrong Input" when I entered integer that doesn't fulfill the boolean (input < 1 || input >4)?
So that if I entered 5, it will also give me "Wrong Input".
Add this:
if(input < 1 || input > 4) {
System.out.println("Wrong input");
}
after input = sc.nextInt();
As of now, your try-catch block is checking if input is an int type. The do-while loop is checking input after it has been entered, so it is useless. The condition must be checked after the user enters what he/she wants. This should fix it:
do
{
try
{
input = sc.nextInt();
if(input < 1 || input > 4) // check condition here.
{
System.out.println("Wrong input");
}
}
catch(Exception e)
{
System.out.println("Expected input to be an int. Try again."); // tell user that input must be an integer.
sc.nextLine();
}
} while (input < 1 || input > 4);
You can also do this:
while (true) {
try {
input = sc.nextInt();
if (input >= 1 && input <= 4) {
break;
}
} catch (Exception e) {
System.out.println("Wrong input");
}
sc.nextLine();
}

Taking keyboard input and running checks on it

I have the following method
public static int modeChooser(){
int choice = 0;
Scanner kb = new Scanner(System.in);
while(choice == 0){
try {
choice = kb.nextInt();
} catch (Exception e) {
continue;
}
if(choice < 1 || choice > 5){
continue;
}
}
return choice;
}
The goal is to only allow the user to put in 1,2,3,4, or 5;
If the user types a string or a too high/low number, the method should just restart until i have the proper int.
Here is an example for the flow:
User types: 1 -> all ok
User types: saddj -> method restarts -> user types 3 --> all ok
Any ideas?
Change to:
do {
// read choice value
if (choice < 1 || choice > 5) {
// hint to user
}
} while(choice < 1 || choice > 5);
I think you can simply put your check in the while condition itself as below:
while(choice < 1 || choice > 5){
try {
choice = kb.nextInt();
} catch (Exception e) {
//ignore the exception and continue
}
}
This way actually works fine:
public static int modeChooser(){
int choice = 0;
Scanner kb = new Scanner(System.in);
while(choice == 0){
try {
choice = kb.nextInt();
} catch (Exception e) {
System.out.println("Sorry but you have to enter 1,2,3,4, or 5! Please try again.");
choice = modeChooser();
}
}
if(choice < 1 || choice > 5){
System.out.println("Sorry but you have to enter 1,2,3,4, or 5! Please try again.");
choice = modeChooser();
}
return choice;
}
if(choice >= 1 && choice <= 5)
break;
else
choice = 0;
If kb.NextInt() fails the data in the input stream remains, you need to skip past it. If you don't skip the invalid data the loop will continuously try, and fail, to read the invalid input resulting in an infinite loop.
You can use kb.next() to skip over the invalid input:
while (true)
{
try
{
choice = kb.nextInt();
if(choice >= 1 && choice <= 5) break;
}
catch (InputMismatchException e)
{
e.printStackTrace();
kb.next();
}
}
I think it's better to use the Scanner.nextLine() and Integer.parseInt() methods:
while(choice < 1 || choice > 5){
try {
choice = Integer.parseInt(kb.nextLine());
} catch (Exception e) {
//...print error msg
}
}
You could include your condition on choice directly in the while condition:
while(choice < 1 || choice > 5){
try {
choice = kb.nextInt();
} catch (Exception e) {
continue;
}
}
(In your current code, is the user enters 7, choice takes that value, the while condition becomes false and your method returns 7, which it should not).
And instead of catching an exception, you could use the hasNextInt() method to make the code cleaner:
public static int modeChooser() {
int choice = 0;
Scanner kb = new Scanner(System.in);
while (choice < 1 || choice > 5) {
if (!kb.hasNextInt()) {
kb.next();
} else {
choice = kb.nextInt();
}
}
return choice;
}
If you do want to use a recursive method, it could look like:
public static int modeChooser() {
Scanner kb = new Scanner(System.in);
while (!kb.hasNextInt()) {
kb.next();
}
int choice = kb.nextInt();
return (choice >= 1 && choice <= 5) ? choice : modeChooser();
}

Try and Catch User Input causes variables to be uninitialized

*EDIT: Okay after fixing the try catch error I get a problem in the catch {.. when it prints.
*, Basically when I say I want to play again it continues the game as it should but it also prints the first catch and then asks for an input at line 23.
if (decision.equalsIgnoreCase("yes"))
{
ai = (int)(Math.random()*101);
System.out.println("From 0 to 100, what number do you think I have generated?");
tryCatch = true;
loop = true;
rtrn = true;
while (tryCatch == true)
{
while (loop == true)
{
try
{
guess = Integer.parseInt(iConsole.nextLine());
if (guess >= 0)
{
loop = false;
}
}
catch (NumberFormatException e)
{
System.out.println("Invalid input. Please try again.");
}
catch (InputMismatchException e)
{
System.out.println("Invalid input. Please try again!");
}
}
Hi this is my first post so if I get the code formatting on the forum wrong I'll edit it.
Right now I'm coding a game in java eclipse where the cpu generates a number and the user has to guess it. I am using the scanner class for most of this. What I am having trouble doing is creating a try catch to check the user input if it is a valid Integer.
What ends up happening is that the code block below it doesn't recognize the already-initialized variable.
package ics3U;
import java.util.*;
import java.io.*;
public class highLow
{
static public void main (String args[]) throws IOException
{
String name;
String decision;
String decision2;
int ai;
int guess;
int counter = 1;
boolean fullGame = true;
boolean tryCatch = true;
boolean rtrn = true;
Scanner iConsole = new Scanner(System.in);
System.out.println("Hello! Welcome to HiLo!");
System.out.println("What is your full name?");
name = iConsole.nextLine();
System.out.println("Hello " + name + "! Would you like to play?");
decision = iConsole.nextLine();
while (fullGame == true)
{
if (decision.equalsIgnoreCase("yes"))
{
ai = (int)(Math.random()*101);
System.out.println("From 0 to 100, what number do you think I have generated?");
tryCatch = true;
rtrn = true;
while (tryCatch == true)
{
try
{
guess = Integer.parseInt(iConsole.nextLine());
}
catch (Exception e)
{
System.out.println("Invalid input. Please try again.");
}
while (guess != ai)
{
if (guess < ai)
{
System.out.println("Too low!");
guess = iConsole.nextInt();
}
else if (guess > ai)
{
System.out.println("Too high!");
guess = iConsole.nextInt();
}
counter = counter + 1;
}
System.out.println("Correct! You guessed it after " + counter + " tries!");
counter = ((counter - counter)+1);
System.out.println("Would you like to play again?");
while (rtrn == true)
{
decision2 = iConsole.next(); //finally..
if (decision2.equalsIgnoreCase("yes"))
{
fullGame = true;
tryCatch = false;
rtrn = false;
break; //do-while may be needed, have to bypass catch, 'break' works after restating value of tryCatch & rtrn
}
else if (decision2.equalsIgnoreCase("no"))
{
System.out.println("Goodbye.");
fullGame = false;
tryCatch = false;
rtrn = false;
iConsole.close();
}
else
{
System.out.println("Sorry?");
}
}
/*catch (Exception e)
{
System.out.println("Invalid input. Please try again.");
}
catch (NumberFormatException e)
{
System.out.println("Invalid input. Please try again.");
}
//More specific Exceptions, turn this on later
catch (InputMismatchException e)
{
System.out.println("Invalid input. Please try again!");
}*/
}
}
else if (decision.equalsIgnoreCase("no"))
{
System.out.println("Goodbye.");
fullGame = false;
tryCatch = false;
rtrn = false;
iConsole.close();
}
else
{
System.out.println("Sorry?");
decision = iConsole.nextLine();
}
}
}
}
Add a continue statement in your catch block. That way, if the user enters something that's not an integer and parsing fails, it will immediately try again rather than trying to run the rest of the loop.
try
{
guess = Integer.parseInt(iConsole.nextLine());
}
catch (Exception e)
{
System.out.println("Invalid input. Please try again.");
continue; // jump to beginning of loop
}
Try moving all your code after the catch block (in the loop) inside the try block after this line
guess = Integer.parseInt(iConsole.nextLine());
As you currently have it, anytime there is an exception in the parseInt, it will still try to process the unassigned guess instead of restarting the loop.
Since the statements are in a try block there's a chance that they will fail, and your program has a chance of trying to use a non-initialized variable. The solution is to initialize the variables to a default value that makes sense, i.e.,
int guess = -1; // some default value
You should also wrap the while loop around the try/catch block. Don't let the program progress until inputted data is valid.
boolean validGuess = false;
while (!validGuess) {
// prompt user for input here
try {
guess = Integer.parseInt(iConsole.nextLine());
if (/* .... test if guess is valid int */ ) {
validGuess = true;
}
} catch (NumberFormatException e) {
// notify user of bad input, that he should try again
}
}
You could even encapsulate all of this into its own method if you need to do similar things throughout the program.

A try-catch method in while loop?

I have this code, and I want to put the try-catch inside a while loop. The logic would be, "while there is an input error, the program would keep on asking for a correct input". How will I do that? Thanks in advance.
public class Random1 {
public static void main(String[] args) {
int g;
Scanner input = new Scanner(System.in);
Random r = new Random();
int a = r.nextInt(10) + 1;
try {
System.out.print("Enter your guess: ");
g = input.nextInt();
if (g == a) {
System.out.println("**************");
System.out.println("* YOU WON! *");
System.out.println("**************");
System.out.println("Thank you for playing!");
} else if (g != a) {
System.out.println("Sorry, better luck next time!");
}
} catch (InputMismatchException e) {
System.err.println("Not a valid input. Error :" + e.getMessage());
}
}
Here I have used break and continue keyword.
while(true) {
try {
System.out.print("Enter your guess: ");
g = input.nextInt();
if (g == a) {
System.out.println("**************");
System.out.println("* YOU WON! *");
System.out.println("**************");
System.out.println("Thank you for playing!");
} else if (g != a) {
System.out.println("Sorry, better luck next time!");
}
break;
} catch (InputMismatchException e) {
System.err.println("Not a valid input. Error :" + e.getMessage());
continue;
}
}
boolean gotCorrect = false;
while(!gotCorrect){
try{
//your logic
gotCorrect = true;
}catch(Exception e){
continue;
}
}
You can add a break; as the last line in the try block. That way, if any execption is thrown, control skips the break and moves into the catch block. But if not exception is thrown, the program will run down to the break statement which will exit the while loop.
If this is the only condition, then the loop should look like while(true) { ... }.
You could just have a boolean flag that you flip as appropriate.
Pseudo-code below
bool promptUser = true;
while(promptUser)
{
try
{
//Prompt user
//if valid set promptUser = false;
}
catch
{
//Do nothing, the loop will re-occur since promptUser is still true
}
}
In your catch block write 'continue;' :)

Categories

Resources