0

I am trying to write a program to ask a user to enter their age and prompt them to re-enter if they enter an improper value (such as a negative number, older than 120, an age with special characters or letters, an out of range number etc...)

I tried writing a try/catch to ask the user to re-enter their age:

System.out.println("Enter your age (a positive integer): ");
    int num;

    try {
        num = in.nextInt();
        while (num < 0 || num > 120) {
            System.out.println("Bad age. Re-enter your age (a positive integer): ");
            num = in.nextInt();
        }
    } catch (InputMismatchException e) {
        //System.out.println(e);
        System.out.println("Bad age. Re-enter your age (a positive integer): ");
        num = in.nextInt();
    }

When the age entered contains special characters/letters or is out of range, the program DOES print out the words "Bad age. Re-enter your age (a positive integer)," however it immediately terminates thereafter with this error:

Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Unknown Source)
at java.base/java.util.Scanner.next(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
at Age.main(Age.java:21)

My goal is to get the program to continue prompting for a valid age until the user gets its right. I would really appreciate any feedback and help. I am a java beginner :) Thank you

I tried to change put the whole code into a while loop but then it causes an infinite loop... please help!

while (num < 0 || num > 120) {
        try {
            System.out.println("Bad age. Re-enter your age (a positive integer): ");
            num = in.nextInt();
        } catch (InputMismatchException e) {
            System.out.println("Bad age. Re-enter your age (a positive integer): ");
        }
    }
taralee98
  • 127
  • 1
  • 12
  • possible dupe of http://stackoverflow.com/questions/13102045/scanner-is-skipping-nextline-after-using-next-nextint-or-other-nextfoo – Scary Wombat Sep 18 '18 at 00:07
  • Don't. Instead put the `try-catch` block in the `loop` and just keep looping until you get what you need – MadProgrammer Sep 18 '18 at 00:08
  • @MadProgrammer Can you please explain what you mean by that? Which loop should I put it in? – taralee98 Sep 18 '18 at 00:14
  • @taralee98 Since there is only one loop in your example code, instead that one – MadProgrammer Sep 18 '18 at 00:16
  • @MadProgrammer I tried that but it caused an infinite loop :( I posted the code above. Any idea where I went wrong? – taralee98 Sep 18 '18 at 00:33
  • @taralee98 Also read the linked questions/answer from ScaryWombat – MadProgrammer Sep 18 '18 at 00:52
  • When you have invalid input and the scanner throws an exception, the invalid input just stays there in the scanner's buffer. The next time through the loop, your code simply tries to read the same invalid input. You need to clear out that invalid input before trying again, either by reading to the end of the line, calling `in.skip()`, or (best, in my opinion) reading the entire line as a string and attempting the parse yourself, as in [the answer by @MadProgrammer](https://stackoverflow.com/a/52377513/535871). – Ted Hopp Sep 18 '18 at 01:09

2 Answers2

1

Since you're trying to capture an invalid input state while still prompting the user for a correct value, the try-catch should be encapsulated within the loop as part of it's validation process.

When reading input using nextInt, invalid input is not removed, so you will need to ensure that you clear the buffer before attempting to re-read it, using nextLine. Or you could just forego it and just read the String value using nextLine directly and then convert it to an int using Integer.parseInt, which is, personally, less troublesome.

Scanner scanner = new Scanner(System.in);
int age = -1;
do {
    try {
        System.out.print("Enter ago between 0 and 250 years: ");
        String text = scanner.nextLine(); // Solves dangling new line
        age = Integer.parseInt(text);
        if (age < 0 || age > 250) {
            System.out.println("Invalid age, must be between 0 and 250");
        }
    } catch (NumberFormatException ime) {
        System.out.println("Invalid input - numbers only please");
    }
} while (age < 0 || age > 250);

The uses a do-while loop, basically because, you have to iterate at least once even for a valid value on the first pass

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Even if you were able to prompt the user to re-enter his age, you would not be able to check wheter the input is correct afterwards. Therefore, I would recommend using a simple while loop, like you are doing, but instead of looking only for a range of number, check whether or not it is a number before trying to parse it in int.

If you use input.nextLine().trim(); for instance, you could use methods such as StringUtils.isNumeric or you could implement your own method to return a boolean value indicating if the input is numeric.

scopchanov
  • 7,966
  • 10
  • 40
  • 68
hugo_lv
  • 1
  • 1