1
    // Precondition: number provided is a positive integer
    // Postcondition: returns a integer of length 4
     public static int validateNumber(int num, Scanner scan)
{
    int number = num;
    while(number < 1000 || number > 9999)
    {
        try
        {
            System.out.print("Number must be 4 digits long. Please provide the number again: ");
            number = scan.nextInt();    // reads next integer provided                                      
            scan.nextLine();
        }
        catch(InputMismatchException e) //outputs error message if value provided is not an integer
        {
            System.out.println("Incorrect input type.");
        }
    }
    return number;
}

Assuming the preconditions are met, when this method gets executed and after entering a string to test the program, I get an infinite loop. Why is this problem occurring and how would I fix it?

Alan
  • 153
  • 1
  • 4
  • 11
  • have you confirmed the length of the numbers you are entering – Ross Drew Dec 23 '13 at 10:09
  • Have you tried printing number after assigning it the next value to check it's reading ok? – Paul Brindley Dec 23 '13 at 10:13
  • how about debugging it? – aviad Dec 23 '13 at 10:13
  • @Alan What is the scanner that you're providing in the input. Is it new Scanner(System.in) – aquaraga Dec 23 '13 at 10:16
  • @Alan Then it shouldn't be a problem. The program will prompt you to re-enter the number. If you enter a four-digit number, the method returns. – aquaraga Dec 23 '13 at 10:19
  • This is what I said. His code works fine. Just called it with `int num = validateNumber(12345, new Scanner(System.in));` and looped until I wrote 1234. – Sergi Dec 23 '13 at 10:20
  • I think i wasn't too clear on what I planned to do. Yes the code works fine but I'm trying to cover for the exception when a string is provided AFTER method execution. That's when I get the infinite loop – Alan Dec 23 '13 at 10:22
  • @Sergi I was the first up-voter of your comment "Works fine for me" :-). I was thinking if the OP was wrapping the Scanner over a gazillion-line file or a socket. – aquaraga Dec 23 '13 at 10:24
  • For instance: Please provide a number: 12111 Number must be 4 digits long. Please provide the number again: alan – Alan Dec 23 '13 at 10:24
  • 1
    @Alan Ahh.. I get it now, just put a number = scan.nextLine(); in the exception block as well. – aquaraga Dec 23 '13 at 10:26
  • yup works for me but it's actually just scan.nextLine() – Alan Dec 23 '13 at 10:30
  • Does `-123` count as four digits? – Dawood ibn Kareem Dec 23 '13 at 11:25
  • @David Wallace I didn't realize that but yes it is – Alan Dec 23 '13 at 19:03
  • Edited above to account for only positive integers for return value – Alan Dec 23 '13 at 19:16
  • Refer to http://stackoverflow.com/questions/3572160/infinite-looptry-catch-with-exceptions?rq=1 for further explanation – Alan Dec 24 '13 at 19:57

4 Answers4

3

To avoid infinite loop when the exception is thrown, you must skip the current line and move on to the next line for processing. Currently, when the exception is thrown, you are re-iterating and scanning the same line which again throws exception and hence you are stuck in infinite loop.

I think you need to write the scan.nextLine() method call when an exception is thrown.

catch (InputMismatchException e) // outputs error message if value provided is not an integer
            {
                System.out.println("Incorrect input type.");
                // Moved the nextLine() method call over here
                scan.nextLine();
            }

Also modify the logic to detect if the number is 4 digit or not. Use integer comparison using< and > instead of converting the number into string.

Ankur Shanbhag
  • 7,746
  • 2
  • 28
  • 38
  • 3
    an explanation of what and why you are changing is more of an answer than just code : http://meta.stackexchange.com/questions/148272/is-there-any-benefit-to-allowing-code-only-answers-while-blocking-code-only-ques – Ross Drew Dec 23 '13 at 10:15
2

Why not

number < 1000 || number > 9999

instead of

String.valueOf(number)).length() != 4

It looks much cleaner and is probably more efficient.

Ingo
  • 36,037
  • 5
  • 53
  • 100
0

Code looks OK, but consider this instead:

while ((int)Math.log10(number) != 3)
Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

One problem i can see just see your try catch block carefully-

If you input a non-integer input then scanner.nextInt() will throw an InputMisMatchException and the control will come to catch block so finally a new value is not assigned to the number so again condition met for because its checking with the previous number itself.

Just try if it works if it doesn't then please send your input cases so that we can analyze and also tell us what is the initial value of num in method you are passing.

Ravi Kumar
  • 993
  • 1
  • 12
  • 37