0

I'm trying to make up the most compact solution for reading an integer from a user using only nextInt() method and the exceptions it throws to exclude errors... This is the code i have for now:

Scanner sn = new Scanner(System.in);

    boolean inputNotNull = true;
    while (inputNotNull) {
        try {
            int number = sn.nextInt();

            System.out.printf("The number %d is power of 2: %b\n", number, isPowerOfTwo(number));
            if (number == 0) {
                inputNotNull = false;
            }
        }
        catch(InputMismatchException e) {
            System.err.println("Wrong input! Input only integer numbers please...");
    }

    }

So, what this is supposed to do is wait for an integer from a user. If the user enters 0 end the program. My idea was to try to exclude the scenario when the user enters something else than integer with use of InputMismatchException (I know it is not the best practice to catch RuntimeException). When the exception is raised an error message is printed, and the program returns to the while loop, asking again for the input as nothing happened.

Approach that I am using here has a flaw that when the user enters something that is not an integer value, program prints out the error message repeatedly, looping on forever.

How to avoid this?

As a side question how would you solve this problem that I am trying to solve?

Falko
  • 15,326
  • 12
  • 50
  • 91
slimDeviant
  • 247
  • 4
  • 13
  • Why don't you just get the line (string, not int) and try to parse it as int? You won't need to catch an exception and this will bring you to next line – Semyon Danilov Nov 13 '14 at 13:11
  • possible duplicate of [\[Infinite Loop\]Try.. catch with exceptions](http://stackoverflow.com/questions/3572160/infinite-looptry-catch-with-exceptions) – Tom Jul 26 '15 at 10:29

3 Answers3

5

Reason for infinite loop is that when you try entering input, you press enter key and that extra character (enter) is disregarded by scanner when calling nextInt. Hence when you enter invalid number you get exception and scanner again sees enter character as you didnt consumed that character and hence you never come out of it.

In order to avoid it try consuming that character when you get exception like:

catch (InputMismatchException e) {
    System.err.println("Wrong input! Input only integer numbers please...");
    sn.nextLine();
}

And that should resolve your issue.

SMA
  • 33,915
  • 6
  • 43
  • 65
0
int Scanner::nextInt(int radix)

Scans the next token of the input as an int. Returns the int scanned from the input. Throws: InputMismatchException - if the next token does not match the Integer regular expression, or is out of range NoSuchElementException - if input is exhausted IllegalStateException - if this scanner is closed

Your approach is correct. You need to add within your catch:

sn.nextLine(); // eats up newline char

If the user keys in wrong data repeatedly, this will also show errors repeatedly till the user provides correct input (int). You may add another exception NoSuchElementException, come out of the loop if input exhausted

Dr. Debasish Jana
  • 6,653
  • 3
  • 24
  • 55
0

It's usually a bad practice to catch unchecked exception, I suggest this:

Scanner sn = new Scanner(System.in);

boolean inputNotNull = true;
while (inputNotNull) {
    String line = sn.nextLine();
    Integer number = null;
    try {
        number = Integer.parseInt(line);
    } catch (NumberFormatException e) {
        System.err.println("Wrong input! Input only integer numbers please: " + e.getMessage());
        continue;
    }
    System.out.printf("The number %d is power of 2: %b\n", number, isPowerOfTwo(number));
    if (number == 0) {
        inputNotNull = false;
    }
}
Semyon Danilov
  • 1,693
  • 1
  • 16
  • 35