0
votes

I have a while loop that is supposed to catch a non-int input and ask the user to re-enter an int. However it just endlessly loops the error message. Does anyone have an idea why its not not allowing scanner input the second time through?

  while(!enteredInt)
  {
      try
      {
          locus = input.nextInt();
          enteredInt = true;
      }
      catch (Exception e)
      {
          //user didn't type an integer
          System.out.println("You didn't enter a valid number, re-enter point where you will build your city");
      }
  }
2
What is input in this context?templatetypedef
What kind of object is input? a Scanner?Santiago Alessandri
Catching Exception is very bad, don't do it. It could be a NullPointerException but you would never know. It would also produce the results you are describing.unholysampler

2 Answers

9
votes

When you enter a token which is not a number, calling nextInt does not move the scanner beyond the token. As a result, it's just reading the same token over and over.

Here's the documentation for nextInt: http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html#nextInt%28%29 (although the relevant behavior is actually described in the version which takes an argument, here: http://download.oracle.com/javase/6/docs/api/java/util/Scanner.html#nextInt%28int%29 )

So, to give you a quick example, let's assume that the input string is "1 2 Foo". I will add an X to show where the Scanner is currently positioned. It starts out "X1 2 Foo". Then the first call to input.nextInt() happens. It returns 1 and now we're at "1 X2 Foo". Then the second call to input.nextInt() happens. It returns 2 and now we're at "1 2 XFoo". Then the third call to input.nextInt() happens. It doesn't return, but rather throws an InputMismatchException and it also doesn't advance the Scanner. So we're still at "1 2 XFoo". So when we call it a fourth or fifth time, the same thing happens.

To solve this problem, an input.next() call will consume the next token, whatever it is. After this call, in our example, we would be at "1 2 FooX".

Note, however, that the call to input.next() can also still throw exceptions. Specifically, it can throw IllegalStateException if the Scanner is closed (which shouldn't happen in your code) or NoSuchElementException if the Scanner has reached the end of input (which won't happen if you're reading in from the keyboard, as I assume that you are). But just to be safe, you should either catch those errors and break out of the loop or not catch them and instead declare them as thrown by your method.

2
votes

As stated in the documentation:

When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.

So the same(not integer) token will keep throwing the Exception.

You can use next() method to retrieve that token inside the catch.