0

I've implemented a method that asks the user to enter a value. If said value is out of range or it isn't the correct type of value, it should show an error message and then ask again.

public static Integer getValue (Integer minValue, Integer maxValue) {
    Scanner input;
    input = new Scanner (System.in);
    Integer value;
    value = null;
    while (true) {
        try {
            value = input.nextInt();
            input.nextLine();
            if ((value >= minValue) && (value <= maxValue)) {
                break;
            } else {
                // Shows message that says value is not in range.
                continue;
            }
        } catch (InputMismatchException IME) {
            // Shows message that says value is not an integer.
            input.next();
            continue;
        }
    }
    input.close();
    return(value);
}

The code can identify correctly when it's being given an undesired value. The problem comes when the value is actually correct, then it just hangs and takes me to the debugger.

This is an example of an execution:

Select the type of furniture:
1. - Dresser.
2. - Shelf.
3. - Rectangular table.
4. - Round table.
You chose: abc // Asks again because the value entered is not int.
a b c
adsf
5 // Asks again because the value entered is not in range.
1 // Here it is when the compiler takes me to the debugger.

Here's what happens if i force the execution past this point; it shows me the menu below then it completely crashes after asking the user for another value:

Select the type of wood.
1. - Mahogamy.
2. - Cherry-tree.
3. - Walnut.
4. - Pine tree.
5. - Oak tree.
You chose: Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at java.util.Scanner.nextInt(Unknown Source)
    at java.util.Scanner.nextInt(Unknown Source)

This is how it's being called from main:

furnitureMenu();
indexTree = getValue(minIndexFurniture, maxIndexFurniture);
woodMenu();
indexWood = getValue(minIndexWood, maxIndexWood);

It's crucial that I get this method to work because, as shown above, I'll require an input from the user several other times, and not just to select from menus, but also to get specifications for the furniture such as dimensions and what not.

All help is appreciated. Thanks in advance.

ShadowGeist
  • 71
  • 1
  • 3
  • 9
  • I had no issue running this function on my computer. – Falla Coulibaly Sep 18 '16 at 00:10
  • @FallaCoulibaly Can you call it a second time inside your main and see if it hangs or crashes like it did for me? – ShadowGeist Sep 18 '16 at 00:15
  • I did call it from the main like this `Integer indexTree = getValue(0, 4);` – Falla Coulibaly Sep 18 '16 at 00:20
  • try to `clean build` your project that might help. – Falla Coulibaly Sep 18 '16 at 00:39
  • @FallaCoulibaly It's still not doing anything for me. I suspect the problem lies with the scanner not getting new lines to read or something like that. I'm not familiar enough with the functions of scanner to get to the answer myself. – ShadowGeist Sep 18 '16 at 00:45
  • Remove `input.nextLine()` and `input.next()` in the catch. Since the `NoSuchElementException` is thrown when the you are trying to read a value after the scanner reached it's last element thus two line will be the only ones able to throw that error. – Falla Coulibaly Sep 18 '16 at 00:55
  • @FallaCoulibaly I tried that. If I enter a correct value right away, it crashes. If I enter a value outside of range THEN a correct value, it crashes. If I enter garbage (such as not integers) and THEN a correct value, it still keeps asking me eternally. It's definitely down to the way it gets the input from scanner, that much is for sure. – ShadowGeist Sep 18 '16 at 01:09

2 Answers2

0

I already came to a conclusion myself after looking exhaustively for other related questions to mine in this site. This is the one question that solved it: java.util.NoSuchElementException - Scanner reading user input

When you call, sc.close() in first method, it not only closes your scanner but closes your System.in input stream as well.

As seen in my question, my code instantiated a new scanner inside my method, and after a correct value was entered, the method closes the scanner, which prevents new input to be entered after the method is called subsequently.

This is the revision i made:

public static Integer getValue (Scanner input, int minValue, int maxValue) {
    int value;
    value = 0;
    while (true) {
        try {
            value = input.nextInt();
            if((value < minValue) || (value > maxValue)) {
                // ERROR message goes here
            } else {
                break; // Input successful, break loop.
            }
        } catch (InputMismatchException IME) {
            // ERROR message goes here.
            input.nextLine(); // Discards input so user can try again
        }
    }
    return (value);
}

As seen in this revision, the scanner was previously instantiated in the main function and passed as an argument so it can retrieve input from the user inside the method in subsequent calls.

I also improved the way it receives input taking notes from Deitel's book, Java How To Program Chapter 11: Exception Handling, and I adapted it to my specific case.

ShadowGeist
  • 71
  • 1
  • 3
  • 9
0
public static Integer getValue(Integer minValue, Integer maxValue) {
        Scanner input;
        input = new Scanner(System.in);
        int value;
        while (true) {

 System.out.println("Please enter a value");
            if(!input.hasNextInt()) {
                System.out.println("That's not a number!");
                input.next(); // this is important!
            }
            value = input.nextInt();
            if ((value >= minValue) && (value <= maxValue)) {
                return value;
            } else {
                System.out.println("Wrong value please provide a valid input");
            }
        }

    }

Try this. It may help achieving what you want to do.

Sahil Manchanda
  • 9,812
  • 4
  • 39
  • 89
  • This answer doesn't have any exception handling. As shown in my original question, the method needs to know whether the input that is being given is garbage or not (such as a double or a string when an integer is needed), and deal with it accordingly. – ShadowGeist Sep 18 '16 at 13:38
  • It does pretty much the same as the answer I gave, except that mine is arguably cleaner since it was directly picked up from a reliable source (Deitel's book). I appreciate your effort to help me tho. – ShadowGeist Sep 18 '16 at 15:39