1

I'm trying to write a function to validate the user's input. It only returns when the user inputs a double number.

private static double getDouble(String name) {
    double res = 0;
    Scanner s = new Scanner(System.in);
    while (true) {
        System.out.println("Please input " + name + ":");
        if (s.hasNextDouble()) {
            res = s.nextDouble();
            break;
        }
        else s.nextLine();
    }
    s.close();
    return res;
}

However, it only works first time. If I call the function second time right after the first time, the nextLine() will throw an exception.

double length = 0, width = 0;
length = getDouble("length of picture");
width = getDouble("width of picture");

Please see the Output Screenshot

Could someone tell me what the mistake I have made here? And how to fix/avoid it?

Thank you.

  • 1
    Possible duplicate of [java.util.NoSuchElementException - Scanner reading user input](https://stackoverflow.com/questions/13042008/java-util-nosuchelementexception-scanner-reading-user-input) – Benjamin Urquhart Jul 15 '19 at 03:28

2 Answers2

3

I have made another way for getting user input. Just refer to the code and code comments for details.

private static double getDouble(String name) {
    double res = 0;
    Scanner s = new Scanner(System.in);
    while (true) {
        try {
            System.out.print("Please input " + name + ":");
            res = Double.parseDouble(s.nextLine()); // Just get the user input as a string then try to convert it into a double
            break; // if there is no error in the string to double conversion it means that the input is valid, thus break the loop
        } catch (Exception e) { // catch possible errors in case the input is invalid
            System.out.println("Your input is invalid!"); // print desired error message then the loop will execute again getting another user input
        }
    }
    s.close();
    return res;
}

EDIT It is because you have close the scanner instance after the method. Refer to this why that won't work. You could also refer to that for alternatives.

If you want to use hasNextDouble then you could either pass the scanner as a parameter to your getDouble method or declare the scanner as a class variable. Both will result to only declaring and closing 1 Scanner.

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        double tmp = getDouble(s, "Tmp");
        double tmp2 = getDouble(s, "Tmp");
        s.close();
    }

    private static double getDouble(Scanner s, String name) {
        double res = 0;
        while (true) {
            System.out.println("Please input " + name + ":");
            if (s.hasNextDouble()) {
                res = s.nextDouble();
                break;
            } else
                s.nextLine();
        }
        return res;
    }
Mark Melgo
  • 1,477
  • 1
  • 13
  • 30
1

When you close the Scanner object (s.close();) for System.in you can't use scanner again until you restart your application. It's best to leave the Scanner object open until you are absolutely sure you won't need it again.

Personally, I really don't like purposely relying on exceptions to take care of invalid situation but in this case it's extremely suited for it:

private static double getDouble(String name) {
    double res = 0.0d;
    Scanner s = new Scanner(System.in);
    while (res == 0.0d) {
        System.out.print("Please input " + name + ": --> ");
        try {
            res = s.nextDouble(); 
        } 
        catch (Exception e) { 
            // If input is invalid
            System.out.println("Your input is invalid! Numerical Values Only!"); 
            /* Clear the scanner buffer otherwise the response 
               above will continue to display over and over 
               again.            */
            s.nextLine();   
            res = 0.0d;
        }
    }
    return res;
}

You can also do this without using an exception trap:

private static double getDouble(String name) {
    String res = "";
    Scanner s = new Scanner(System.in);
    while (res.equals("")) {
        System.out.print("Please input " + name + ": ");
        res = s.nextLine();
        /* If the User supplies anything that is NOT a string 
           representation of a signed or unsigned integer or 
           double type numerical value. A regular Expression is 
           used here with the String#matches() method.       */
        if (!res.matches("-?\\d+(\\.\\d+)?")) {
            // Input is invalid...
            System.out.println("Your input is invalid (" + res + ")! Only Integer or Double Type Numerical Values Are Allowed!");
            res = "";
        }
    }
    return Double.parseDouble(res);
}
DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22