0

The getSelection method allows the user to input a number in reference to a command list. If the user enters a valid number the code runs flawlessly. How ever if the user enters an invalid number the code will succefully call the testSelection method and properly run untill the getSelection method is recalled. When the method is recalled it keep skipping the user_input line (in debugging mode) and then throws a no such element error. I know this means it is getting a null pointer but I cannot get the code to pause to allow the user to enter a new choice.

I have tried to add a if statement with scan.hasNext to make sure the user has input a new choice and a scan.nextLine to move the scanner to a new line. I do not think these work because the scanner is created and closed every time the method is ran. That being said I cannot understand why it skips the input the second call. I have also tried making the getSelection method recall the method if valid is false and have testSelection return false if the input does not meet requirements.

public static String getSelection() {
        Scanner scan = new Scanner(System.in);
        System.out.println("Please enter selection: ");
        String user_input = scan.next();
        scan.close();
        boolean valid;
        try{
            valid  = testSelection(Integer.parseInt(user_input));
        } catch(NumberFormatException e) {
            valid = testSelection(-1);
        }
        if(valid == true) {
            return user_input;
        }
        return "Error";
    }
    public static boolean testSelection(int i) {
        if(i == -1) {
            System.out.println("Please enter an integer (1-7).");
            getSelection();
        }
        if(i > 7 || i < 1) {
            System.out.println("Invalid Selection");
            getSelection();
        }
        return true;
    }

The output should be getting a user choice from a list of commands until a proper command is entered.

S. Morrison
  • 49
  • 1
  • 10

1 Answers1

0

There are a few things going on in the code that could be modified.

  1. scan.next() throws a NoSuchElementException if there's nothing in the scanner to get. See here.
  2. Since you're reading input from the keyboard (which could not be a number), scan.next() will stop at the next whitespace token whereas scan.nextLine() will stop at the next newline character.
  3. The testSelection(-1) is unnecessary.
  4. testSelection(int) calls getSelection() opening you up to potential recursion problems.
  5. Closing the scanner will close the underlying stream, in this case System.in which will stop you from being able to read from it.

Here's a complete, working example to get a number from 1-7 from the keyboard.

import java.util.Scanner;

public class App {

    private static final int INVALID_SELECTION = 0;

    public static void main(String...args) {
        Scanner scanner = new Scanner(System.in);
        int selection = getSelection(scanner);
        System.out.printf("Selection value: %d", selection);
        scanner.close();
    }

    public static int getSelection(Scanner scanner) {
        int selection = INVALID_SELECTION;
        for (int attempt = 0; attempt < 5; attempt++) {
            System.out.println("Enter a number between 1 and 7: ");
            if (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                try {
                    selection = Integer.parseInt(line);
                } catch (final NumberFormatException e) {
                    System.out.printf("The input %s cannot be converted to a number%n", line);
                }
            }
            if (selection < 1 || selection > 7) {
                System.out.println("Input is not valid.");
            } else {
                return selection;
            }
        }
        return INVALID_SELECTION;
    }

}
William Burnham
  • 4,234
  • 1
  • 13
  • 28