0

I have this code. It asks for two integer values. If the first number is not an integer, then it throws an exception and asks the number again. My code works but I'm wondering if there is a better way to do this:

boolean validInput = false;
boolean validInput2 = false;

while (validInput == false) {
    try {
        Scanner scanner = new Scanner(System.in);
        System.out.print("What is the first number? ");
        int firstNum = scanner.nextInt();
        validInput = true;
    } catch (InputMismatchException e) {
        System.out.println("It's not an integer.");
    }
}

while (validInput2 == false) {
    try {
        Scanner scanner2 = new Scanner(System.in);
        System.out.print("What is the second number? ");
        int secondNum = scanner2.nextInt();
        scanner2.close();
        validInput2 = true;
    } catch (InputMismatchException e) {
        System.out.println("It's not an integer.");
    }
}

I suppose I can do something like this as well. Right?

while (validInput == false) {
    Scanner scanner = new Scanner(System.in);
    System.out.print("What is the first number? ");
    if (scanner.hasNextInt()) {
        int firstNum = scanner.nextInt();
        validInput = true;
    }
}

In the second example when the hasNextInt() method is called, the scanner waits for a value, that makes sense, and if the condition becomes true, nextInt() is called, but nextInt() doesn't wait for input anymore. How does nextInt() know what the entered value was when the condition executed?

CROSP
  • 4,499
  • 4
  • 38
  • 89
Zoltan King
  • 1,964
  • 4
  • 18
  • 38

2 Answers2

1

This is the way I would do it:

int firstNum;
int secondNum;
String num;
String errMsg = "Invalid Input - Integer Only!";

Scanner scanner = new Scanner(System.in);

while (true) {
    System.out.print("What is the first number? ");
    num = scanner.nextLine();
    if (num.matches("\\d+")) {
        firstNum = Integer.parseInt(num);
        break;
    }
    System.out.println(errMsg);
}       

while (true) {
    System.out.print("What is the second number? ");
    num = scanner.nextLine();
    if (num.matches("\\d+")) {
        secondNum = Integer.parseInt(num);
        break;
    }
    System.out.println(errMsg);
}   

System.out.println();    
System.out.println("First Number:  --> " + firstNum);
System.out.println("eacond Number: --> " + secondNum);   

For getting numerical input from a User, I prefer using the Scanner.nextLine() method in conjunction with the String.matches() method and a simple Regular Expression ("\\d+"). You don't need to trap an exception this way. I just find it more flexible.

Declare your variables before the while loops, that way you can use them after the while loops or even within other while loops if you like. Break out of a loop once you've acquired and validated what you need.

DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22
  • Thank you but \\d+ matches double values as well. I only wanted it for integers. – Zoltan King Oct 21 '19 at 11:09
  • @ZoltanKing - No, I'm afraid you are mistaken. It **does not** match double type values. Or do you mean it matches more than one integer digit?. If you want to deal with a single digit then remove the **+** character from the expression so that it is just **"\\d"**. Read up on [RegEx Metacharacters](https://www.vogella.com/tutorials/JavaRegularExpressions/article.html#meta-characters). – DevilsHnd - 退職した Oct 21 '19 at 12:43
0

After using nextInt(), you must clear the input buffer of the new line character still there from when the user pressed Enter by using nextLine() before trying nextInt() again, eg:

System.out.print("What is the first number? ");
int firstNum = scanner.nextInt();
scanner.nextLine(); // <-- add this line

Still better would be to read the whole line in and parse it as an integer in one shot:

int firstNum = Integer.parseInt(scanner.nextLine()); // do it in 1 line

Still better again is to write a reusable method that keeps trying to parse an integer, and if it doesn't read a valid integer, ask the user to retry (left to reader to implement).

Bohemian
  • 412,405
  • 93
  • 575
  • 722