Gavin Hayes
Gavin Hayes

Reputation: 23

repeatedly asking for user input until they enter "quit"

Why does the code break when the default case of the switch function is used.

import java.util.Scanner;

public class Main {
   static void checkCommand(String command)
   {
       switch (command) {
           case "add" -> System.out.println("added");
           case "access" -> System.out.println("accessed");
           case "compare" -> System.out.println("compared");
           default -> {
               System.out.println("Invalid command, please try again");
               enterCommand();
           }
       }
   }

   static void enterCommand(){
       System.out.print(">>> ");
       Scanner usrInput = new Scanner(System.in);
       String input = usrInput.nextLine();
       while (!input.equals("quit")){
           checkCommand(input);
           System.out.print(">>> ");
           input = usrInput.nextLine();
       }
   }

   public static void main(String[] args) {
       enterCommand();
   }
}

When I enter in "add", "compare", or "access", and then "quit", the program works as intended, but if I enter in anything that is incorrect where it uses the default case, the program breaks and repeatedly asks for input even if the input is "quit". I have tried a few different things to fix it and nothing has worked. I'm trying to keep the switch statement but if there isn't a way to keep it and have the program run as intended I am open to other options.

Upvotes: 0

Views: 419

Answers (2)

Pines Tran
Pines Tran

Reputation: 679

You need to understand the recursive mechanism. When the latest recursive has done, it needs to do the remaining tasks from previous recursive. I added comments into your code to explain:

    static void checkCommand(String command){
            switch (command) {
                // ... 
                default: {
                    System.out.println("Invalid command, please try again");
                    enterCommand(); // recursive is calling here.
                }
            }
   }
   static void enterCommand(){
           System.out.print(">>> ");
           Scanner usrInput = new Scanner(System.in);
           String input = usrInput.nextLine();  // time 1: input: test  | time 2: input: quit -> done recursive 1.
           while (!input.equals("quit")){
               checkCommand(input);             // time 1: go to default and call recursive, go to input time 2
               System.out.print(">>> ");        // Do the remaining task from time 1. In case you input time 3: "quit". the program will exit.
               input = usrInput.nextLine();
           }
  }

The more recursives are called, the more remain tasks need to do. In your code, to quit the program, you need to type "quit" (n + 1) times if the recursive is called n times

Solutions: To quit immediately after typing "quit" in the first time, just remove the recursive call.

default: {
       System.out.println("Invalid command, please try again");
}

Upvotes: 3

Abra
Abra

Reputation: 20914

Your code works for me. The only problem is that I have to enter quit twice, after entering an invalid command, in order for the program to terminate.

Here is output from a sample run of the exact same code as in your question:

>>> access
accessed
>>> add
added
>>> george
Invalid command, please try again
>>> compare
compared
>>> quit
>>> quit

I am required to enter quit twice because method enterCommand is being called from method checkCommand. You don't need to do this. The while loop, in method enterCommand will ensure that the user is prompted again to enter a command – even after [s]he has entered an invalid command.

Calling enterCommand from checkCommand means that you are essentially calling enterCommand recursively. In the above output, I needed to enter quit twice, since I only entered a single, invalid command. I suggest that you run your code in a debugger to understand why you get this behavior.

As @OldDogProgrammer wrote in his comment to your question, you should create a Scanner object only once rather than each time method enterCommand executes.

As @MadProgrammer wrote in his comment, a do-while loop may be more appropriate than a plain while loop.

Also, quit is not an invalid command so I think that you need to handle that command in method checkCommand and the handling is that you just ignore the command. Since you are using switch expressions, I couldn't find a way to "ignore" a case so in the below code I simply print an empty string. Alternatively, you could print an appropriate message such as Good bye, for example.

import java.util.Scanner;

public class Main {
    private static Scanner usrInput;

    static void checkCommand(String command) {
        switch (command) {
            case "add" -> System.out.println("added");
            case "access" -> System.out.println("accessed");
            case "compare" -> System.out.println("compared");
            case "quit" -> System.out.print("");
            default -> {
                System.out.println("Invalid command, please try again");
            }
        }
    }

    static void enterCommand() {
        String input;
        do {
            System.out.print(">>> ");
            input = usrInput.nextLine();
            checkCommand(input);
        } while (!input.equals("quit"));
    }

    public static void main(String[] args) {
        usrInput = new Scanner(System.in);
        enterCommand();
    }
}

Here is the output when I ran the above code:

>>> access
accessed
>>> add
added
>>> George
Invalid command, please try again
>>> compare
compared
>>> quit

As you can see, I only need to enter quit once.

Upvotes: 3

Related Questions