3

Suppose I need to keep on asking the user till he enters a double.

What I did is I used a while loop and checking if there is an exception or not.

If there is an exception, I would go and ask for the next input.

double bal = 0;
Scanner sc = new Scanner(System.in);
while (true) {
    try {
        System.out.println("Enter the balance");
        bal = sc.nextDouble();
        break;
        } catch (Exception e) {
          System.out.println("That isn't a number");
    }
}
System.out.println("Bal is " + bal);
sc.close();

But if I enter a non-double then it doesn't ask for the next input, keeps on printing those two lines ending in an infinite loop.

Enter the balance
XYZ
That isn't a number
Enter the balance
That isn't a number
Enter the balance
That isn't a number
Enter the balance
That isn't a number
....

What is that I'm missing?

Uma Kanth
  • 5,659
  • 2
  • 20
  • 41
  • Possible duplicate of http://stackoverflow.com/questions/23676834/infinite-loop-on-scanner-hasnext-reading-from-a-file (and others) – yshavit Aug 31 '15 at 06:32
  • Also http://stackoverflow.com/questions/7446379/how-do-i-safely-scan-for-integer-input. – Codebender Aug 31 '15 at 06:33
  • Also, catching the exception probably isn't the best way of handling the control flow. You can (and probably should) use hasNextDouble instead – yshavit Aug 31 '15 at 06:33
  • @yshavit I also used `hasNextDouble()` it also ended in an infinite loop. Didn't know to discard that input. So I wanted to ask why it was like that. This is just an illustrative example to dipict the situation. – Uma Kanth Aug 31 '15 at 06:36

3 Answers3

11

You need to discard the previous input from the stream by calling sc.next() in your catch block. Sadly, the scanner does not do this automatically when the input fails.

Zarwan
  • 5,537
  • 4
  • 30
  • 48
  • Oh.. I was just facing this problem and never faced before. Could you please elaborate on a bit deeper details here? so, if I have a=scanner.nextInt(); in the try block, and I deliberately want an Exception to happen (and it's all in the while), why a=scanner.nextInt(); doesn't ask for a new input? – Giorgi Tsiklauri Sep 07 '19 at 17:08
5

Use sc.next() to discard the erroneous input:

while (true) {
    try {
        System.out.println("Enter the balance");
        bal = sc.nextDouble();
        break;
    } catch (InputMismatchException e) {
        System.out.println("That isn't a number");
        sc.next();
    }
}

Also I recommend to catch the specific exception (InputMismatchException in this case). This way you will not erroneously print "That isn't a number" if some other problem occurs (for example, standard input stream is closed).

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
2

From nextDouble documentation:

If the translation is successful, the scanner advances past the input that matched.

So when the input doesn't match, the scanner does not advance past it. So next iteration when you do nextDouble the input hasn't been cleared and it'll still read the same input.

You should either advance the input by reading next() when you fail or read the input as string and try to parse the result, that way even if the value is illegal, the input has been cleared and next iteration you can read a new value / input:

public static void main(String[] args) {
    double bal = 0;
    Scanner sc = new Scanner(System.in);
    while (true) {
        try {
            System.out.println("Enter the balance");
            bal = Double.parseDouble(sc.next());
            break;
            } catch (Exception e) {
              System.out.println("That isn't a number");
        }
    }
    System.out.println("Bal is " + bal);
    sc.close();
}
Ori Lentz
  • 3,668
  • 6
  • 22
  • 28