Do-While loop with try and catch exits loop without asking for new input

89 Views Asked by At

I have to create a do-while loop to validate any user input that is not a double and is not zero. I've been looking around on here and googling, I was creating an infinite loop, but I figured that out by wiping out the input. However, now the program is not asking for user input again and the loop is breaking. Not really sure what I broke. This is just one part of the code, I also have to do this do-while loop for wallWidth.

**EDIT so now I got the first loop working, but there seems to be something wrong with the second variable's input wallWidth. No matter what I input, it does not keep looping if I enter incorrect input and it seems to always be assigned to zero. I've added all the code here and the output at the bottom.

public class Paint1 {

    public static void main(String[] args) {  
        Scanner scnr = new Scanner(System.in);  
        double wallHeight = 0.0;  
        double wallWidth = 0.0;  
        double wallArea = 0.0;  
        double gallonsPaintNeeded = 0.0;  
        boolean decimal = false;  

        
        final double squareFeetPerGallons = 350.0;  
        
        // Implement a do-while loop to ensure input is valid
        // Prompt user to input wall's height
        do {  
            try {  
                System.out.println("Enter wall height (feet): ");  
                wallHeight = scnr.nextDouble();  
                
                if (wallHeight <= 0) { //non zero numbers  
                    throw new Exception("Invalid Input");  
                }  
                decimal = true;  
            }  
            catch (Exception e) {  
                System.out.println("Invalid Input");  
                scnr.nextDouble(); //wipe out user input  
            }  

        } while (!decimal);  
        do {  
            try {  
                System.out.println("Enter wall width (feet): ");  
                wallWidth = scnr.nextDouble(); //width input  

                if (wallWidth <= 0) {  
                    throw new Exception("Invalid Input");  
                }  
                decimal = true;  
            }  

            catch (Exception e) {  
                System.out.println("Invalid Input");  
                scnr.nextLine(); // wipeout  
            }  
        } while (!decimal);  

        // Calculate and output wall area  
        wallArea = wallHeight * wallWidth;  
        System.out.println("Wall area: " + wallArea + " square feet");  

        // Calculate and output the amount of paint (in gallons) needed to paint the wall  
        gallonsPaintNeeded = wallArea / squareFeetPerGallons;  
        System.out.println("Paint needed: " + gallonsPaintNeeded + " gallons");  

    }  
}  

The loop stops and still creates the exception without continuing after clearing the invalid input.

Enter wall height (feet): 
thirty
Invalid Input
Exception in thread "main" java.util.InputMismatchException
 at java.base/java.util.Scanner.throwFor(Scanner.java:939)
 at java.base/java.util.Scanner.next(Scanner.java:1594)
 at java.base/java.util.Scanner.nextDouble(Scanner.java:2564)
 at Paint1.main(Paint1.java:31)
Enter wall height (feet): 
30
Enter wall width (feet):
0
Invalid Input
Wall area: 0.0 square feet
Paint needed: 0.0 gallons
3

There are 3 best solutions below

2
Baran On

What happens is when you try to wipe out user input with scnr.nextDouble() it throws InputMistMatchException, which isn't handled. This is because the provided input does not match the expected type. To overcome this in your context, you can use scnr.nextLine(). Because what ever you input it can be interpreted as string.

2
Elliott Frisch On

You should check if there is a double available with Scanner.hasNextDouble() before you attempt to read a double with a Scanner. Similarly, you should check if there is a line of input with Scanner.hasNextLine() before reading (and discarding) any non-double token. Like,

do {
    try {
        System.out.println("Enter wall height (feet): ");
        // Is there a double available?
        if (scnr.hasNextDouble()) {
            wallHeight = scnr.nextDouble();
            if (wallHeight <= 0) {
                throw new Exception("Invalid Input");
            }
            decimal = true;
        } else if (scnr.hasNextLine()) {
            // Consume the next non-double token
            scnr.nextLine();
        } else {
            // There's no more input, end the loop
            break;
        }
    } catch (Exception e) {
        System.out.println("Invalid Input");
    }
} while (!decimal);
1
DevilsHnd - 退した On

As a suggestion, don't throw an exception if the User enters a wrong value type or a typo. Validate that entry and if it's incorrect, let him/her try again and make a proper entry, for example:

Scanner userInput = new Scanner(System.in);
String ls = System.lineSeparator();

double feet;
String inFeet = "";
while (inFeet.isEmpty()) {
    System.out.print("Enter wall height (in feet): ");
    inFeet = userInput.nextLine().trim();
    /* Is the User entry a string representation of a unsigned
       integer or floating point value and is that value greater
       than 0?              */
    if (!inFeet.matches("\\d+(\\.\\d+)?") || Double.parseDouble(inFeet) <= 0) {
         System.out.println("Entry (" + inFeet + "): -> Error - Invalid Wall "
                          + "Height Entry! Try again..." + ls);
         inFeet = "";  // Empty `inFeet` to ensure re-loop:
    }
}
// If code makes it to here then the entry is valid!

feet = Double.parseDouble(inFeet);
System.out.println("User Entry: -> " + feet + " feet.");

Console Output:

Enter wall height (in feet): 0
Entry (0): -> Error - Invalid Wall Height Entry! Try again...

Enter wall height (in feet): 14.25
User Entry: -> 14.25 feet.

Convert the while loop to a do/while if you need to.