0

How do you capture the enter key when using hasNextInt()? I have the following code and am trying to exit gracefully if the user just enters the return key. In the example below I was expecting to get back -9, but the program just hangs on the hasNextInt() line

import java.util.Scanner;
public class InputInt{
    public static void main(String[] args){
        InputInt x = new InputInt();
        System.out.println(x.enterInt());
    }
    public int enterInt(){
        int myInt = -9;
        boolean isValid = false;
        String lf = "";
        
        Scanner kb = new Scanner(System.in);
        
        while(!isValid){
            System.out.print("please enter an integer: ");
            if(kb.hasNextInt()){
                myInt = kb.nextInt();
                isValid = true;
            }else{
                lf = kb.nextLine();
                if (lf.length() == 0)isValid = true;
                
            }            
        }        
        return myInt;
    }
   
}
DCR
  • 14,737
  • 12
  • 52
  • 115
  • 1
    Personally, I'd use one `Scanner` with `nextLine` to read the input from the user and then a second `Scanner` to parse it for [example](https://stackoverflow.com/questions/28260016/java-while-loop-until-user-enters-a-value-of-0/28260037#28260037), but for some reason, people don't like that approach, alternatively, you could use `nextLine` to get the next line of input and simple try using `Integer.parseInt` and handle the exception, for [example](https://stackoverflow.com/questions/71551770/java-and-nextint-what-if-user-just-hits-enter/71552149#71552149) – MadProgrammer Mar 30 '22 at 20:34
  • @MadProgrammer That's an interesting approach. Even though I think `hasNextInt()` and `nextInt()` still use `Integer.parseInt` and `NumberFormatException` under the covers, it is a clean approach. – David Conrad Mar 30 '22 at 20:48
  • @DavidConrad The problem with `hasNextInt` in this context, is how it handles the enter key, it doesn't seem to "consume" it or produce an error (at least not immediately). If you're scanning a file or something, then it's probably okay. I also prefer not to use `try-catch` as a flow control mechanism, but that's me :P – MadProgrammer Mar 30 '22 at 20:50
  • @DCR This kind of thing does get asked a bit, but finding a "clean" solution isn't always easy, I prefer to make use of some kind of re-usable workflow if I can, [for example](https://gist.github.com/RustyKnight/93f07a59b1b17af7da9d7a5f15aa79a1). This is just a conceptual idea and one which you could grow more ideas from if you wanted – MadProgrammer Mar 30 '22 at 21:42
  • @MadProgrammer Right, but my point is, it's still using `try-catch` as a flow control mechanism, it's just hidden inside the standard library code. – David Conrad Mar 31 '22 at 14:20

1 Answers1

3

When asking for user input, always use nextLine(), which clears the input buffer (including the trailing newline), then check/parse the input for correctness:

while (true) {
    System.out.print("Please enter an integer: ");
    String input = kb.nextLine();
    if (input.matches("\\d{1,8}")) {
        myInt = Integer.parseInt(input);
        isValid = true;
        break;
    } else if (input.ieEmpty()) {
        break;
    } else {
        System.out.print("1 to 8 digits only please, or blank to exit.");
}

The final else is optional, but a nice touch.

The limiting of input to up to 8 digits means you'll never get a error on parsing. To allow every valid integer using regex, see this answer (it's ugly, so viewer discretion is advised).

Note also the more succinct and conventional while (true) with break combination, which obviates the need for overloading the isValid variable, which now means the user entered a valid integer.

To also allow negative numbers, use instead:

if (input.matches("-?\\d{1,8}"))
Bohemian
  • 412,405
  • 93
  • 575
  • 722