Infinite loop on one hand, NoSuchElementException on the other

483 Views Asked by At

I recently asked if there is any possible way whatsoever to get an exception from assigning a value to a String variable with the Scanner (The thread is here:)

And one of the guys told me that CTRL+D would be a case where a NoSuchElementException could be thrown. This to me is kind of a special case because input.nextLine() returns a String, and a String can be basically anything a user could type on the keyboard, so one would assume that input.nextLine() would not be a concern to throw an exception.

So I decided to add some try catch blocks into a program I'm writing on the off chance that CTRL+D is pressed when the program is asking for a number.

The problem I've run into is that when I catch the CTRL+D exception, the Scanner needs to be flushed, but if I flush the Scanner, it will cause a NoSuchElementException to occur because no new line exists. I'm using this all in a while true loop, so I'm kind of stuck between a rock and a hard place.

I will post one version of the code, with the input.nextLine() commented out. If you run it as is, you will get the infinite loop that happens when the Scanner needs to be flushed. If you uncomment the input.nextLine(), that very line of code will itself cause a NoSuchElementException.

import java.util.NoSuchElementException;



private int getMainOptions(){

    System.out.printf("\n********** Main Options **********");
    System.out.printf("\n*%32s*", "");
    System.out.printf("\n*  %-30s*", "[1] Create Customer");
    System.out.printf("\n*  %-30s*", "[2] Create Reservation");
    System.out.printf("\n*  %-30s*", "[3] Display Customer");
    System.out.printf("\n*  %-30s*", "[4] Display Reservation");
    System.out.printf("\n*%32s*", "");
    System.out.printf("\n**********************************");

    while(true){
        try{

            System.out.print("\nChoose Option: ");

            if(input.hasNextInt()){
                return input.nextInt();
            }

            System.out.print("\nInvalid option");
            input.nextLine();
            continue;
        }

        catch(NoSuchElementException e){
            System.out.print("\nAn exception occurred.");
            //input.nextLine();
        } 
    } 


}

Apart from creating the Scanner inside the while loop and destoying it in the catch to be recreated in the next iteration, what can be done to solve this problem?

2

There are 2 best solutions below

0
On

The code goes into an infinite loop when the input.nextLine() is commented out or when input.hasNextLine() is there to check because it is in a while(true) loop with nothing to stop it since input.nextInt() is not called. if(input.hasNextInt()) will not wait for an int, but simply skip the code inside the if statement if an int is not present as input. Instead try this:

while(true){
    try{
        System.out.print("\nChoose Option: ");
        String in=input.nextLine();
        try{
            int i=Integer.parseInt(in);
            return i;
        }catch(NumberFormatException ex)
        {
            System.out.print("\nInvalid option");
        }
    }
    catch(NoSuchElementException e){
        System.out.print("\nAn exception occurred.");
        //input.nextLine();
    } 
} 
}

I hope this helps and that I am understanding the question correctly

0
On

I'm not sure you fully grasp what happens when the user presses Ctrl-D. When that happens the standard input stream is closed. There is no way to reopen a closed stream. Even if you create a new Scanner and pass it in System.in it will still throw a NoSuchElementException.

As a Linux user if I press Ctrl-D in an interactive program, I expect the program to terminate. That is really all you can do at that point.