Infinite Looping Caused by Exception Handling - java

What I want this code to do is handle the exception, and then simply repeat. What it does instead, unfortunately, is loop infinitely... I can't figure out why.
It never asks for the input to be re-entered, seemingly setting it for good the first time. However, this ONLY happens when an exception is thrown; if the user enters an invalid integer, there is no problem at all with the looping process.
I'm relatively new to all this, so I was hoping to get a second opinion before just forcing the loop to exit when an exception is caught.
Scanner scan = new Scanner(System.in);
// Variables associated with the clock:
private int h; // h = Hours
private int m; // m = Minutes
private int s; // s = Seconds
public boolean userPrompt() {
String answer = "";
// Loops while until a clock is generated and selected
while (! answer.equals("y")) {
System.out.println("What time is it?");
try {
// Asking for the time, one variable at a time.
System.out.print("H >> ");
h = scan.nextInt();
System.out.print("M >> ");
m = scan.nextInt();
System.out.print("S >> ");
s = scan.nextInt();
// Testing for the validity of the clock's time:
if ((h < 24 && h >= 0) && (m < 60 && m >= 0) && (s < 60 && s >= 0)) {
// Displaying the formatted clock's time:
System.out.printf("Clock { %02d:%02d:%02d }\n", h, m, s);
System.out.println("Save clock generated?");
System.out.print("Answer (y/n): ");
answer = scan.next();
}
} catch (InputMismatchException iox) {
// Here lies the issue, I think...
System.out.println("ERROR: " +iox);
}
}
// A safeguard for the next method in the program
return answer.equals("y");
}

use finally after catch block and put the following two statements in it like this :
try {
} catch(InputMismatchException iox) {
} finally {
System.out.print("Answer (y/n): ");
answer = scan.next();
}
Note : When exception occurs before System.out.print("Answer (y/n): "); and
answer = scan.next(); statements,these two statements are not executed.But the statements within the finally block executes regardless of what happens within the try block.So,if you use the two statements in finally block these will always be executed infinite looping won't happen.

Related

Prompt to continue while loop conflict

What seems fairly simple has got me completely confused. I ask the user for some inputs at the beginning of a while loop to be able to execute a program inside the loop. After the program is executed, I want to prompt the user at the end of the loop to restart or end the loop.
I am trying to make the loop ask only the LAST question after it has completed the program within it. Then, if the user has answered "yes", the loop will restart. Any other answer will result in ending the loop.
Here is my code
String rerun = null;
boolean run = true;
int x;
int y;
while (run = true)
{
// first question
x = keyboard.nextInt();
y = keyboard.nextInt();
// run program with x and y
// second question (ask to continue)
rerun = keyboard.nextLine();
if (rerun.equalsIgnoreCase("yes"))
{
continue;
}
else
{
run = false;
//break; stops the loop without answering the second question
}
}
Sample input/output:
Enter height and width of the house you want me to draw: 4 4
Program runs...
Bob, do you want me to draw another house for you (yes to continue)?
Enter height and width of the house you want me to draw (must be even numbers):
Why is it asking me the height and width again even though I have conditions at the end, prohibiting the loop to restart before I prompt it to continue?
Thank you!
Try this.
I haven't changed your code much, but I've printed a prompt on the screen before asking for a user input and printed the user input on the screen before restarting the loop. You could also do a try and catch block as below and see where the exception occurs. Also this would help in cause if a user enters a String instead of int for x or y.
import java.util.Scanner;
public class Test {
public static void main(String args[]) {
String rerun = null;
boolean run = true;
Scanner keyboard = new Scanner(System.in);
while (run == true) {
int x = 0;
int y = 0;
String val = "";
System.out.print("Enter x int : ");
try {
x = keyboard.nextInt();
}
catch (Exception ex) {
System.out.println("Error at x : " + ex.getMessage());
}
System.out.print("Enter x int : ");
try {
y = keyboard.nextInt();
}
catch (Exception ex) {
System.out.println("Error at y : " + ex.getMessage());
}
System.out.print("Enter string : ");
try {
val = keyboard.nextLine();
}
catch (Exception ex) {
System.out.println("Error at string: " + ex.getMessage());
}
System.out.println("x : " + x + ", y : " + y + ", val : " + val);
}
}
}
The problem is that after you use the nextInt() method the 'end of line' character is still in the input buffer. You must manually flush the buffer by calling nextLine(). I have modified your code below to show how you can fix this.
// first question
x = keyboard.nextInt();
y = keyboard.nextInt();
// run program with x and y
//Flush Input Buffer
keyboard.nextLine();
// second question (ask to continue)
rerun = keyboard.nextLine();
From your question it looks as though you want the loop to run at least once before the test. If that's the case then a do while loop is probably more appropriate than a while loop.
A do while loop looks something like:
do {
int x = keyboard.getInt();
int y = keyboard.getInt();
// process
System.out.println("Do you want to continue?");
} while (keyboard.nextLine().equalsIgnoreCase("yes"));
That seems to me to capture your intent better than the while loop of your original code and avoids having a keepRunning boolean (which I find confusing to read).
If you find the while statement confusing, rather than going back to a boolean variable, you can split the test into a separate method:
do {
...
} while (shouldRepeat());
private boolean shouldRepeat() {
System.out.println("Do you wish to continue?");
String answer = keyboard.nextLine();
return answer.equalsIgnoreCase("yes");
}
In my view that is still a clearer and less fragile solution than having a flag that is set.

need to output error if anything EXCEPT 1 or 2 is input by user

So it looks like it allows me to input all ints, and when i do a string or anything else it does give me error, but how do I go about making it so its ONLY 1 and/or 2 accept and 3,4,5....(every other number) are not excepted...
Code below
public static void main(String[] args){
System.out.println("Please enter 1 to add or 2 to multiply. "); // ask user to input 1 or 2
Scanner in = new Scanner(System.in);
try {
int add = in.nextInt(); // add for 1
int multiply = in.nextInt(); // multiply for 2
}
catch (Exception e) {
System.out.println("Operation failed. You need to enter 1 or 2.");
}
}
Exceptions here would be overkill IMO. Just using if else clauses would work equally well. Like this:
if(input == 1) {
// add
}
else if(input == 2) {
// multiply
}
else {
System.out.println("Operation failed. You need to enter 1 or 2.");
}
Also if you want the program to keep prompting you can just wrap it in a loop. Here is a small example using a boolean sentinel to keep the loop going. This is one of many ways to implement this task.
public static void main(String[] args) {
System.out.println("Please enter 1 to add or 2 to multiply. "); // ask user to input 1 or 2
Scanner in = new Scanner(System.in);
boolean inputNotValid = true;
while(inputNotValid){
int input = in.nextInt();
if(input == 1) {
inputNotValid = false;
//add
System.out.println("adding");
}
else if(input == 2) {
inputNotValid = false;
//multiply
System.out.println("multiplying");
}
else {
System.out.println("Operation failed. You need to enter 1 or 2. Try again");
}
}
}
Replace:
int add = in.nextInt(); // add for 1
int multiply = in.nextInt(); // multiply for 2
with:
int value = in.nextInt();
if(value == 1) // do add
if(value == 2) // do multiply
// else case = error
The whole program would become:
public static void main(String[] args)
{
System.out.println("Please enter 1 to add or 2 to multiply. ");
Scanner in = new Scanner(System.in);
try
{
int value = in.nextInt();
if (value == 1)
{
System.out.println("add");
// do add
}
else if (value == 2)
{
System.out.println("mult");
// do multiply
}
else
{
// error
System.out.println("Operation failed. You need to enter 1 or 2.");
}
}
catch (Exception e)
{
System.out.println("Read operation failed. This should not happen!");
}
}
The javadoc for nextInt() says:
Scans the next token of the input as an int.
An invocation of this method of the form nextInt() behaves in exactly the same way as the invocation nextInt(radix), where radix is the default radix of this scanner.
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
You still can catch the InputMismatchException, the NoSuchElementException and the IllegalStateException, since in.nextInt() can throw them. You could also catch Exception (the only superclass of all three exceptions) instead.
Since Exception is an unchecked Exception, you can also remove the try-catch. Beware though, that an error in the Input will then exit the whole program.

How to properly use try-catch?

I'm trying to process how to use try-catch. I understand it'll 'try' the main code, and if it doesn't work it'll catch it and execute something different. I want to also keep prompting the user to enter a proper value.
I keep getting the inputmismatch exception error, even if I set my catch to have that in its block.
To clarify: The try-catch is going to be there for when I ask the user for ints on how long they plan to stay, and what floor they'd like to be on. Therefore, the errors I'd like to handle involve non-integers and if they are out of bounds of the 'hotel'.
Here is my code:
public class Hotel{
public static void main(String[] args) throws IOException {
int choice = 0;
String guestName = " ";
int stayTime = 0;
int floorPref = 0;
System.out.println("Welcome to the Hotel California.");
Scanner sc = new Scanner(System.in);
Room[][] hotel = new Room[8][20];
for(int i = 0; i< hotel.length; i++){
for(int j = 0; j<hotel[i].length;j++){
hotel[i][j] = new Room(0,false,"none",0.00,0);
int roomNum = ((i+1) * 100) + (j + 1);
hotel[i][j].setRoom(roomNum);
int roomCheck = hotel[i][j].getRoomNumber();
if(roomCheck > 500){
hotel[i][j].setPrice(350.00);
}
else if(roomCheck < 500){
hotel[i][j].setPrice(200.00);
}
}
}
// Guest check-in interface.
do{
System.out.println("What business have you today?");
System.out.println("1. Guest Registration");
System.out.println("2. Guest Checkout");
System.out.println("3. Show me occupied rooms");
System.out.println("4. Exit");
choice = sc.nextInt();
if(choice == 1){
System.out.println("Tell us about yourself.");
System.out.println("Please input your name:");
guestName = sc.next();
System.out.print("How long are you planning to stay?");
try{
stayTime = sc.nextInt();
}
catch(InputMismatchException e){
System.out.println("Please input a valid integer.");
stayTime = sc.nextInt();
}
System.out.println("Great. What floor would you like to be on? Enter a number 1-8, 0 for no preference.");
floorPref = sc.nextInt();
System.out.println("The following rooms are available based on your floor preference (floors 1-8, 0 for no preference: ");
}
if(floorPref > 0){
for(int i = 0; i < hotel[floorPref].length; i++){
if(hotel[floorPref][(i)].getOccupation() == false){
System.out.print("Rooms " + hotel[floorPref-1][i].getRoomNumber() + ", ");
}
}
System.out.println("Are available today.");
}
else if(floorPref == 0){
for(int i = 0; i < hotel.length; i++){
for(int j = 0; j < hotel[i].length; j++){
System.out.print("Room " + hotel[i][j].getRoomNumber() + ", ");
}
}
System.out.println("Is available.");
}
}while(choice != 4);
}
}
The try-catch block you have right now is flawed, because once you get inside the catch block, all the user has to do is enter something that's not an integer to crash your whole program.
Instead, to get stayTime and all the other ints you pull from the Scanner, create a separate function that blocks until the user enters an int:
private static int parseIntFromScanner(Scanner sc) {
while(true) {
try {
int toReturn = sc.nextInt();
return toReturn;
} catch(InputMismatchException ime) {
//Continue back to the top of the loop, ask again for the integer
}
}
}
try to put this at the top of your code
import java.util.InputMismatchException;
import java.util.Scanner;
import java.io.IOException;
and in your public static void throws IOException main delete throws IOException so it only remains public static void main
hope it will works
the following is small piece of code to divide.If user enters zero then it will go to catch and you can also enter number.
Note
the code will go catch only once.I have used depracated methods.This is just an example as per your requirement.
import java.io.DataInputStream;
import java.io.IOException;
public class test1 {
public static void main(String args[]) throws NumberFormatException, IOException
{
DataInputStream d=new DataInputStream(System.in);int x;
try {
x=Integer.parseInt(d.readLine());
int z=8;
System.out.println(z/x);
} catch (Exception e)
{
System.out.println("can not divide by zero");
x=Integer.parseInt(d.readLine());
}
}
}
To answer your question as to why it's still failing: all of the calls to nextInt() can throw InputMistmatchException, not only the one put inside the try part of a try-catch block. And that's what's happening now.
Another issue is calling nextInt a second time inside the catch block. Exceptions thrown inside a catch block require their own handling, separate from the try-catch block to which they belong. So, if nextInt inside the catch block throws an InputMismatchException, it will leave the try-catch block and work its way out from there. In the case of the posted code, that means main will terminate on the exception.
A side point, as musical_coder pointed out, the code needs to loop with the validation. Otherwise, it would end up without setting values if the second attempt to read a value fails.
BTW, see this: Redoing a try after catch in Java, for a tip on scanner use that will lead to more headaches. In fact, it tells why the handling with the try-catch you have now will always end up terminating the program. (it's a matter of how Scanner functions)

How to repeat until the user enters an integer?

This is currently my code.
What I want it to do, is accept up to 10 numbers in an array then do and display some math for them. What I managed to do, is catch errors, then stop the program.
What I want it to do, is keep the program running until the user correctly enters an integer.
I managed to do something similar for my y/n string, but I don't know how to do it for integer arrays.
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
int i=0, numberlist[] = new int [10];
String yn=null;
while (i < 10)
{
try {
System.out.print("Please enter your number\n");
numberlist[i]=input.nextInt();
System.out.print("Would you like to enter another number? (y/n)\n");
yn=input.next();
i++;
if (i==10)
{System.out.println("You reached the maximum amount of numbers\n");
break;}
if (yn.equals("n"))
break;
else if (!yn.equals("y"))
while (true)
{System.out.print("Please only enter a 'y' for yes or 'n' for no next time.\nDo you understand? Type 'y' to continue\n");
yn=input.next();
if (yn.equals("y"))
break;
}
}catch (Exception e){System.out.println("Please enter the correct number(integers only) next time.");}
}
int max=numberlist[0], min=numberlist[0], numlength = i, sum=0;
float average;
for(i = 0; i < numlength; i++) {
if(numberlist[i] > max)
max = numberlist[i];
}
for(i = 0; i < numlength; i++) {
if(numberlist[i] < min)
min = numberlist[i];
}
for(i = 0; i < numlength; i++) {
sum=numberlist[i]+sum;
}
average = (float)sum/(float)numlength;
System.out.println("Your Sum is: "+sum);
System.out.println("Your Average is: "+average);
System.out.println("Your Maximum is: "+max);
System.out.println("Your Minimum is: "+min);
}
Move your error handling for numbers inside the while loop so that any exceptions don't break the flow out of the loop and end the program.
while (i < 10) {
try {
System.out.print("Please enter your number\n");
numberlist[i] = input.nextInt();
System.out.print("Would you like to enter another number? (y/n)\n");
yn = input.next();
i++;
if (i == 10) {
System.out.println("You reached the maximum amount of numbers\n");
break;
}
if (yn.equals("n"))
break;
else if (!yn.equals("y"))
makeUserUnderstand(input,
"Please only enter a 'y' for yes or 'n' for no next time.");
} catch (InputMismatchException e) {
makeUserUnderstand(input,
"Please enter the correct number (integers only) next time.");
}
}
I've moved out the common "Do you understand?" part into a method.
private static void makeUserUnderstand(Scanner input, String msg) {
while (true) {
System.out.println(msg);
System.out.println("Do you understand? Type 'y' to continue\n");
if (input.next().equals("y"))
break;
}
}
First of all, don't catch Exception. You should catch only the specific exceptions that you care about and know might occur in your code. Any other exceptions indicate a serious problem and by catching them, you can accidentally squelch important information that indicates a bug that needs your attention.
With that said, you can solve your problem by making your try block smaller by only wrapping the code that reads input. In addition, create a loop that checks a flag that indicates if an error occurred. The flag can be set in the catch block when an error occurs parsing the input into an integer.
If you have trouble translating my description into code, feel free to ask about the details.

Easier way to guarantee integer input through Scanner?

For a program I am writing, I need to ask a user for an integer between 1 and 8. I've tried multiple (cleaner) ways of doing this but none of them worked, so I'm left with this:
int x = 0;
while (x < 1 || x > 8)
{
System.out.print("Please enter integer (1-8): ");
try
{
x = Integer.parseInt(inputScanner.next());
}
catch(NumberFormatException e)
{
x = 0;
}
}
Where inputScanner is a Scanner. Surely there is a better way?
Scanner does regular expressions, right? Why not check if it matches "^[1-8]$" first?
Using the nextInt() is already an improvement compare to simply using the next() method. And before that, you can use the hasNextInt() to avoid haing all this bunch of useless exceptions.
Resulting in something like this:
int x = 0;
do {
System.out.print("Please...");
if(scanner.hasNextInt()) x = scanner.nextInt();
else scanner.next();
} while (x < 1 || x > 8);
I had to do a graphic interface calculator (works only with Integers), and the problem was, that
the Tests didn't allow any Exceptions to be thrown if the input wasn't
Integer. So I couldn't use
try { int x = Integer.parseInt(input)} catch (Exception e) {dosomethingelse}
Because Java programs generally treat an input to a JTextField as a String
I used this:
if (input.matches("[1-9][0-9]*"){ // String.matches() returns boolean
goodforyou
} else {
dosomethingelse
}
// this checks if the input's (type String) character sequence matches
// the given parameter. The [1-9] means that the first char is a Digit
// between 1 and 9 (because the input should be an Integer can't be 0)
// the * after [0-9] means that after the first char there can be 0 - infinity
// characters between digits 0-9
hope this helps :)
You could try something like this:
Scanner cin = new Scanner(System.in);
int s = 0;
boolean v = false;
while(!v){
System.out.print("Input an integer >= 1: ");
try {
s = cin.nextInt();
if(s >= 1) v = true;
else System.out.println("Please input an integer value >= 1.");
}
catch(InputMismatchException e) {
System.out.println("Caught: InputMismatchException -- Please input an integer value >= 1. ");
cin.next();
}
}
Apache Commons is your friend. See NumberUtils.toInt(String, int)
String input;
int number;
while (inputScanner.hasNextLine())
{
input = inputScanner.nextLine();
if (input.equals("quit")) { System.exit(0); }
else
{
//If you don't want to put your code in here, make an event handler
//that gets called from this spot with the input passed in
try
{
number = Integer.parseInt(input);
if ((number < 1) || (number > 8))
{ System.out.print("Please choose 1-8: "); }
else { /* Do stuff */ }
}
catch (NumberFormatException e) { number = 0; }
}
}
I always like to pull in the full string so you can be sure that the user pushed the Enter button. If you just use inputScanner.nextInt() you can put two ints on a line and it will pull in one, then the other.
Example code:
int x;
Scanner in = new Scanner(System.in);
System.out.println("Enter integer value: ");
x = in.nextInt();
An array can also be used to store the integer.

Categories

Resources