2

I wrote this simple code to fetch a double and just keep asking until one was given, but when you give a string it just turns into an infinite loop and I can't figure out why. Any reason why it behaves this way?

Scanner scanner = new Scanner(System.in);   
double x = 0.0d;

while (true) {
    try {
        System.out.println("Gimme a double:");

        x = scanner.nextDouble();
        break;
    } catch (InputMismatchException e) {}           
}

System.out.println(x);
Seralize
  • 1,117
  • 11
  • 27
  • 1
    You should never swallow exceptions the way you are doing. At least put a print statement in there so you would see that the loop continuously executes the exception and skips your break statement. – Vincent Ramdhanie May 01 '13 at 00:06
  • I found out by putting a print statement in the catch block, but I didn't see a point bringing it into the example code. – Seralize May 01 '13 at 00:08

3 Answers3

7

It becomes an infinite loop if an invalid double value is entered initially. Control then enters the exception block. Because Scanner#nextDouble does not consume new line characters, these values are repeatedly passed through to the statement

x = scanner.nextDouble();

which doesn't block having already received input. This results in an infinite loop.

Rather than having an empty exception block, Scanner#nextLine should be used to consume the newline character.

} catch (InputMismatchException e) {
    System.out.println("Error found: " + scanner.nextLine() + " continuing...");
}

such that the Scanner#nextDouble line will block for IO in the next iteration.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
2

According to the javadocs for Scanner#nextDouble, the characters are not consumed if the conversion to double is not successful (but they are if the conversion was successful):

Scans the next token of the input as a double. This method will throw InputMismatchException if the next token cannot be translated into a valid double value. If the translation is successful, the scanner advances past the input that matched.

Sample output of your program:

$ java Main
Gimme a double:
3.5
3.5
$ java Main
Gimme a double:
blah
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
Gimme a double:
(Infinite loop here)

You must consume the characters yourself, preferably in the exception handler:

} catch (InputMismatchException e) {
    System.out.println("Not a double: " + scanner.nextLine());
}

Sample output of changed program:

$ java Main
Gimme a double:
blah
Skipped Past: blah
Gimme a double:
3.56
3.56
rgettman
  • 176,041
  • 30
  • 275
  • 357
1

Reimeus correctly states why the infinite loop occurs. You can fix it by calling scanner.nextLine() in the catch block:

public static void main(String[] args) throws IllegalArgumentException,
        IllegalAccessException {
    /*
     * StackTest t = new StackTest();
     * 
     * for(Field f :t.getClass().getDeclaredFields()){
     * System.out.println(f.get(t)); }
     */

    Scanner scanner = new Scanner(System.in);
    double x = 0.0d;

    while (true) {
        try {
            System.out.println("Gimme a double:");

            x = scanner.nextDouble();
            break;
        } catch (InputMismatchException e) {
            scanner.nextLine();
        }
    }

    System.out.println(x);
}
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189