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

public class h {

    /** Test Function.
     * @param args Kommandozeilenparameter 
     */
    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        int input;
        boolean check = false;
        do {
            try {
                System.out.println("give me a number: ");

                input = scan.nextInt();

                check = true;
            } catch (InputMismatchException e) {
                System.out.println("Eingabe ist falsch");
            }
        } while (!check);
        System.out.println("getout");
    }
}

I am trying to check if the user gives an integer as input. I am trying to catch it with the help of try catch and do while loop.

But it goes to an endless loop.

How can I solve it?

In second time I cannot write anything.

Ben Wainwright
  • 4,224
  • 1
  • 18
  • 36
Birol Yılmaz
  • 109
  • 1
  • 8
  • 2
    The first place you should always go when you have unexpected behavior is the [documentation](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/Scanner.html#nextInt()). `scan.nextInt()` only consumes the input if it can be translated to an integer. Otherwise it leaves it in the scanner's buffered data. So if the user enters a letter, that letter is never consumed, `scan.nextInt()` just keeps reading that same letter over and over and, because it's not an integer, it keeps looping. – Charlie Armstrong Jan 18 '21 at 20:37
  • This is one of the reasons I do not use Scanner, but rather a BufferedReader and using manual means of translation (like Integer.valueOf()). It's a bit wordier and takes more deliberate effort, but it works better in the end. – NomadMaker Jan 18 '21 at 23:32

4 Answers4

3

The first place you should always go when you have unexpected behavior is the documentation. scan.nextInt() only consumes the input if it can be translated to an integer. Otherwise it leaves it in the scanner's buffered data. So if the user enters a letter, that letter is never consumed, scan.nextInt() just keeps reading that same letter over and over and, because it's not an integer, it keeps looping. The fix is to simply read the input from the scanner as a string, whether it can be interpreted as an integer or not. Then you can check if it's an integer yourself, and the input is already consumed. Here's your example, modified:

Scanner scan = new Scanner(System.in);
int input;
boolean check = false;

do {
    try {
        System.out.println("give me a number: ");

        // This retrieves the next line of input, without converting it to an integer:
        String line = scan.nextLine();

        // This tries to convert it to an integer,
        // and throws a NumberFormatException if it can't:
        input = Integer.parseInt(line);

        check = true;
    } catch (NumberFormatException e) {
        System.out.println("Eingabe ist falsch");
    }
} while (!check);

System.out.println("getout");

In order to try to help you visualize my explanation, I'm going to write out a sample input and then I'll show where the data is at each step. Let's say I enter abc into the console, using your original code. The program then enters into an infinite loop, and here's why:

I enter abc into the input stream:

System.in: abc
scan:
input:


scan reads abc from the input stream as it tries to find an integer:

System.in:
scan: abc
input:


scan can't translate abc into an integer, so it throws an exception. But note that scan held on to abc, it doesn't just go away:

System.in:
scan: abc
input:


The same thing happens again, it tries to convert abc to an integer, but it can't, so it throws an exception again. See the infinite loop happening?

System.in:
scan: abc
input:

Now lets try my code. I'll enter abc and then 123:

I enter abc into the input stream:

System.in: abc
scan:
line:
input:


scan reads abc from the input stream because I told it to read the next line:

System.in:
scan: abc
line:
input:


scan passes the data on to line, because it matches the criteria for a line of text:

System.in:
scan:
line: abc
input:


The code tries to parse abc into an integer, but it can't, so it goes to the next loop iteration. line is local to each iteration of the loop, so its old value gets thrown out:

System.in:
scan:
line:
input:


I enter 123 into the input stream:

System.in: 123
scan:
line:
input:


scan reads 123 from the input stream because I told it to read the next line:

System.in:
scan: 123
line:
input:


scan passes the data on to line, because it matches the criteria for a line of text:

System.in:
scan:
line: 123
input:


The code successfully parses 123 into an integer, and assigns it to input. No infinite loop, the program has completed.

System.in:
scan:
line:
input: 123

Charlie Armstrong
  • 2,332
  • 3
  • 13
  • 25
1

You just need to move the check = true assignment into the catch block.

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


class h {

    /** Test Funktion.
     * @param args Kommandozeilenparameter
     */
    public static void main(String[] args) {
        //
        Scanner scan = new Scanner(System.in);
        int input;
        boolean check = false;
        do {
            try {
                System.out.println("give me a number: ");


                input = scan.nextInt();


            } catch (InputMismatchException e) {
                System.out.println("Eingabe ist falsch");
                check = true;
            }
        } while (!check);
        System.out.println("getout");

    }
}

The above code runs until the user inputs something other than an integer, for eg. a character or a decimal. If the user inputs a valid integer, the programs again asks for a number.

In your case, if user inputs a wrong integer, the flow goes to catch block and the statement is printed. No other logic happens to break or continue the loop. As for why the exception happens again and again; the reason is simply that the scanner is still trying to read the previous input and the cycle keeps on repeating.

If you wanted the program to ask for an integer again and again until a correct input is entered, the following code does the job.

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


public class h {

    /** Test Funktion.
     * @param args Kommandozeilenparameter
     */
    public static void main(String[] args) {
        //
        Scanner scan = new Scanner(System.in);
        int input;
        boolean check = false;
        do {
            try {
                System.out.println("give me a number: ");


                input = scan.nextInt();

                check = true;
            } catch (InputMismatchException e) {
                System.out.println("Eingabe ist falsch");
                scan.next();
            }
        } while (!check);
        System.out.println("getout");

    }
}
Jalaj Varshney
  • 131
  • 1
  • 9
1

From javadoc:

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

This means that the input is only 'read' if it is of the correct type. Since your input is not correct, it will not be read and the next time the scanner will try to read that same sequence - resulting in an infinite loop.

To fix this issue, add scan.nextLine() (or other read methods) in your catch block. When I added nextLine(), it worked for me.

Your catch block:

catch (InputMismatchException e) {
    System.out.println("Eingabe ist falsch");
    scan.nextLine();
}
0

You can use Scanner::nextLine instead of Scanner::nextInt

    public class h {
    /**
     * Test Funktion.
     *
     * @param args Kommandozeilenparameter
     */
      public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        int input;
        boolean check = false;
        do {
           try {
               System.out.println("give me a number: ");
               input = Integer.parseInt(scan.nextLine());
               check = true;
               } catch (NumberFormatException e) {
                 System.out.println("Eingabe ist falsch");
           }

         } while (!check);
         System.out.println("getout");
       }
    }
Sergey Afinogenov
  • 2,137
  • 4
  • 13