Skip to content
Advertisement

Java: How to use a Scanner to check that input is an integer and is within a specified range

I’m having trouble with my code.

What it should do:

  • Check if Scanner “myScanner” is an Integer
  • If it is an Integer, if it is between 1 and 200 (both included)

Problem:

  • I need to input an Integer with the correct value twice after the the first guess wasn’t correct.

Here is a screenshot of exactly what I mean: Screenshot of the problem

private static int inputGuess () {
    Scanner myScanner = new Scanner(System.in);
    int guess = 0;
    if (myScanner.hasNextInt()) {
        guess = myScanner.nextInt();
    }
    if (1 > guess || guess > 200) {
        while (!(myScanner.hasNextInt()) || !(1 <= guess && guess <= 200)) {
            while (!myScanner.hasNextInt()) {
                myScanner.nextLine();
            }
            guess = myScanner.nextInt();
            if (!(guess >= 1 && guess <= 200)) {
                myScanner.nextLine();
            }
        }
    }
    return guess;
}

I have tried to apply @Hulk’s (top answer) logic (at least I think I did) into a single method (is sadly a requirement for my project) and got this:

private static int inputGuess () {
    Scanner myScanner = new Scanner(System.in);
    int guess = 0;

    while (!myScanner.hasNextInt() || guess < 1 || guess > 200) {
        while (!myScanner.hasNextInt()) {
            myScanner.nextLine();
        }
        guess = myScanner.nextInt();
        if (guess >= 1 && guess <= 200) {
            break;
        }
    }
    return guess;
}

After a bit of testing still no error! If you still find a mistake I would be happy if you shared it with me!

Advertisement

Answer

This gets a lot simpler if you split your problem into smaller parts. First, solve the “read until we got an integer” part and put it into a method so we can reuse it:

private static int readNumber(Scanner sc) {
     while (!sc.hasNextInt()) { 
         sc.nextLine(); // if its not a number, consume the line and wait for new input
     }
     return sc.nextInt(); // always an integer
}

Now, we only need to add the range check:

private static int inputGuess () {
    Scanner myScanner = new Scanner(System.in);             
    
    int n = 0;
    while (n < 1 || n > 200) { // range check, only in one place
        n = readNumber(myScanner); // always returns a number
    }
    return n;       
}

You basically complicated things too much, by repeating the range check in 3 places in different ways, and it’s easy to get lost with all these negations. Keep your methods simple, and only do one thing at a time!


To adress your updated question: If you absolutely need to inline these into one method, this is the result:

private static int inputGuess () {
    Scanner myScanner = new Scanner(System.in);
    
    int n = 0;
    while (n < 1 || n > 200) { // loop until in valid range
        while (!myScanner.hasNextInt()) { 
         myScanner.nextLine(); // if its not a number, consume the line and wait for new input
        }              
        n = myScanner.nextInt(); // always an integer
    }
    return n; // always in valid range
}

Note that there is still only one place where there is a check for numeric input, and only one place where the range is validated. In programming, there is rarely a reason to write exactly the same thing twice – don’t repeat yourself! – a ‘principle’/guideline sometimes abbreviated as DRY.

Advertisement