1

Help, I am completely new to java and I am trying to create a loop that will ask for an input from the user which is to be a number. If the user enters anything other than a number I want to catch the exception and try again to get the correct input. I did this with a while loop however it does not give the opportunity after the error for the user to type in anything it loops everything else but that. Please help me to see understand what is wrong and the correct way to do this... Thank you. This is what I have:

    import java.util.Scanner;
    import java.util.InputMismatchException;

    public class simpleExpressions {
    public static void main (String[] args) {
      Scanner keyboard = new Scanner(System.in);

      while ( true ) {
        double numOne;
        System.out.println("Enter an Expression ");
        try {
          numOne = keyboard.nextInt();
          break;
        } catch (Exception E) {
          System.out.println("Please input a number only!");
        } //end catch
      } //end while
    } //end main
otis
  • 13
  • 1
  • 5
  • Please don't forget to add a '?' to questions! Some people do a search in the page for '?' and if none exists in the 'question' go directly to the next (actual) question in line. – Andrew Thompson Jan 01 '14 at 14:14

3 Answers3

7
while ( true ) 
{
  double numOne;
  System.out.println("Enter an Expression ");
  try {
    numOne = keyboard.nextInt();
    break;
  }
  catch (Exception E) {
    System.out.println("Please input a number only!");
  }

This suffers from several problems:

  • numOne hasn't been initialized in advance, so it will not be definitely assigned after the try-catch, so you won't be able to refer to it;
  • if you plan to use numOne after the loop, then you must declare it outside the loop's scope;
  • (your immediate problem) after an exception you don't call scanner.next() therefore you never consume the invalid token which didn't parse into an int. This makes your code enter an infinite loop upon first encountering invalid input.
Marko Topolnik
  • 179,046
  • 25
  • 276
  • 399
5

Use keyboard.next(); or keyboard.nextLine() in the catch clause to consume invalid token that was left from nextInt.

When InputMismatchException is thrown Scanner is not moving to next token. Instead it gives us opportunity to handle that token using different, more appropriate method like: nextLong(), nextDouble(), nextBoolean().
But if you want to move to other token you need to let scanner read it without problems. To do so use method which can accept any data, like next() or nextLine(). Without it invalid token will not be consumed and in another iteration nextInt() will again try to handle same data throwing again InputMismatchException, causing the infinite loop.

See @MarkoTopolnik answer for details about other problems in your code.

Pshemo
  • 113,402
  • 22
  • 170
  • 242
Maroun
  • 87,488
  • 26
  • 172
  • 226
  • `keyboard.nextLine();` is not here to consume `\n` but to consume invalid token (along with rest of line but that is not necessary) which is not consumed *when exception is thrown*. So without `nextLine()` or `next()` in catch section which doesn't have problem with consuming this token loop will try to *parse* same data infinitely. – Pshemo Jan 03 '18 at 18:32
  • 4 years ago... I learned a lot. – Maroun Jan 03 '18 at 19:57
  • I tried to correct your answer. If you don't agree with my edit feel free to roll it back. – Pshemo Jan 03 '18 at 20:52
0

You probably want to use a do...while loop in this case, because you always want to execute the code in the loop at least once.

int numOne;
boolean inputInvalid = true;
do {
    System.out.println("Enter an expression.");
    try {
        numOne = keyboard.nextInt();
        inputInvalid = false;
    } catch (InputMismatchException ime) {
        System.out.println("Please input a number only!");
        keyboard.next(); // consume invalid token
    }
} while(inputInvalid);
System.out.println("Number entered is " + numOne);

If an exception is thrown then the value of inputInvalid remains true and the loop keeps going around. If an exception is not thrown then inputInvalid becomes false and execution is allowed to leave the loop.

(Added a call to the Scanner next() method to consume the invalid token, based on the advice provided by other answers here.)

Bobulous
  • 12,241
  • 4
  • 36
  • 63