1

Hi I´m newbie in programming and I have this problem. I want to get input from user , using scanner. Program is supposed to try if input is valid, then call a function to do the job. Problem is I want program to repeat aking for input from user, if input is not valid. So I have try block in a while loop. The problem is on the first iteration of while loop everything is ok but when I insert invalid input and while loop is forced to iterate second time, try block is not executed and boolean which is condition of while loop is not set to false. So while loop runs for ever. Plz be kind.

public static void main(String args[]) {
    Scanner scanner = new Scanner(System.in);
    boolean isRunning = true;
    int input;

    while(isRunning) {
        System.out.println("insert a number:");
        try {
            input = scanner.nextInt();
            inputToString(input);
            isRunning = false;
        } catch(InputMismatchException e) {
            System.out.println("input musi byt cele cislo");
            isRunning = true;
        }

    }
}

public static void inputToString(int input) {
    System.out.println(input);
} 
  • Using punctuation make question more readable. Not all are native English, absence of dot, commas can be problem to understand – Jacek Cz Sep 13 '15 at 11:57

3 Answers3

1

The problem with your approach is that when the input is not a valid int you leave it in the input buffer. The next loop will see exactly the same input, and it would repeat exactly the same actions (throw, catch, continue with the loop).

What you should do is to drop the incorrect input from the scanner when you see that it does not match what you expect. You could do it in your catch block, like this:

try {
    input = scanner.nextInt();
    inputToString(input);
    isRunning = false;
} catch(InputMismatchException e) {
    System.out.println("input musi byt cele cislo");
    isRunning = true;
    scanner.nextLine(); // Drop input from the scanner's buffer
}

A better approach would be to not rely on try/catch in the scanning code at all. Scanner provides a convenient way for you to avoid exceptions: calling hasNextInt before you call nextInt lets you find out ahead of time if the exception would be thrown or not, and clean the wrong data from the buffer:

while(isRunning) {
    System.out.println("insert a number:");
    if (scanner.hasNextInt()) {
        input = scanner.nextInt();
        inputToString(input);
        isRunning = false;
    } else {
        System.out.println("input musi byt cele cislo");
        isRunning = true;
        scanner.nextLine(); // Drop input from the scanner's buffer
    }
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

You need to consume invalid number from Scanner before asking for new one since nextInt didn't consume it, but thrown exception.

} catch (InputMismatchException e) {
    System.out.println("input musi byt cele cislo");
    scanner.next();//consume
    isRunning = true;
}

But you should not use exceptions and try-catch sections as main part of control logic. Scanner provides hasNextInt() method to test if user provided valid input. So your code should be like

System.out.print("give me the money:");//ask user of integer
while(!scanner.hasNextInt()){//test is provided value is valid integer
    String token = scanner.next();//consume incorrect value
    //inform that value is not correct and ask for new one
    System.our.println(token + " is not considered as valid number");
    System.our.print("please try again:");
}
//here we know that user provided valid integer
value = scanner.nextInt();
Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • Thanks your answer really helped me. I didnt know that using try block this way can cause such bugs. Thanks a lot. – Matúš Kačmár Sep 13 '15 at 12:04
  • @MatúšKačmár Actually problem was not caused by fact that you used try-catch, but because you didn't consume incorrect value from scanner. I added second example to show you how you can change your code to not use try-catch since this structure should be used to handle really exceptional cases, not standard control flow since code is less readable, and creating exceptions can be heavy task. – Pshemo Sep 13 '15 at 12:07
  • Ok I understand it now but If I will be not using scanner anymore in the code do I need to close it ? Like scanne.close() method ? or it doesnt matter – Matúš Kačmár Sep 13 '15 at 12:13
  • Closing Scanner will also close stream from which it is reading, so in your case it will close also `System.in` and closed streams can't be reopened which means that current process can't be able to read from them any more. So if you want to close scanner make sure to do it right before your application ends (like at end of `main` method). – Pshemo Sep 13 '15 at 12:16
  • Thanks you saved me from future headaches with this type of tasks. Now I understand it – Matúš Kačmár Sep 13 '15 at 12:20
0

you should reinitialize Scanner reference before scanning input

 public static void main(String args[]) {
    Scanner scanner = null;
    boolean isRunning = true;
    int input;

    while (isRunning) {
        System.out.println("insert a number:");
        try {
            scanner = new Scanner(System.in);
            input = scanner.nextInt();
            inputToString(input);
            isRunning = false;
        } catch (InputMismatchException e) {
            System.out.println("input musi byt cele cislo");
            isRunning = true;
        }

    }
}

public static void inputToString(int input) {
    System.out.println(input);
}

this works

Homo Filmens
  • 116
  • 7
  • Could you explain why this solves the problem? As shown in different answers there are other solutions, so why OP should prefer to reinitialize Scanner? – Pshemo Sep 13 '15 at 12:09
  • 1
    Cause Scanner reference mantains the incorrect input if you don't drop it before doing another iteration. So you have to reinitialize it. But it isn't a correct answer. You should look at @dasblinkenlight solution – Homo Filmens Sep 13 '15 at 12:11