Search code examples
javainputswitch-statementcase

How to stop a user from entering a letter in a switch case when the letter is the first input entered


When using a switch case with integers, I am able to successfully stop the user from crashing the program with a try/catch when they enter a letter (a, b, c, etc, not case specific). However, I can only stop it after an integer is entered. For this example, it is NOT my actual code, it is only an example as it is a general question. Secondly, I want to try and get it working with suggestions, not having it done for me:

int choice
Scanner scan = new Scanner (System.in);

System.out.println ("Enter a number");
System.out.println ("1: Example one");
System.out.println ("2: Example two");
System.out.println ("0: Exit");
choice = scan.nextInt();

Loop: for (;;)
{
    switch (choice)

    case 1: System.out.println ("Example one successful");
            choice = scan.nextInt();
            break;
    case 2: System.out.println ("Example two successful");
            choice = scan.nextInt();
            break;
    case 0: System.exit (0);
            break Loop;
    default: try
             {
                System.out.println ("Please enter a number")
                choice = scan.nextInt();
             }
             catch (InputMismatchException error)
             {
                System.out.println ("Not a valid number: " + error);
                choice = scan.nextInt();
             }

If the user enters a "1", it outputs the proper text inside the case 1 block. The same goes for case 2 and case 0 to exit. It will loop properly and continuously like this:

Enter a number: 1
Example one successful
Enter a number: 1
Example one successful
Enter a number: 2
Example two successful
Enter a number: ghdrf
Not a valid number: java.util.InputMismatchException
Enter a number: 0

The try/catch works in catching the wrong input, all the other case work. The problem is if the user never enters an integer from the start and enters a letter instead. It will throw the InputMismatchException right away. The try/catch doesn't even try to catch it.

My thinking was because I assigned the scanner to read an integer from the start. I tried to start there. I originally tried this between the loop label and the switch statement as it is the only place I could put it to not get an error:

Loop: for (;;)
{
    String letter = input.nextLine();
    if(letter.matches("[1-9]*")
    {
        choice = Integer.valueOf(letter);
    } 
    else 
    {
        System.out.println("Invalid input");
    }

    switch (choice)
    ...

This worked somewhat in the same way as my try/catch except it was simply printing "invalid input" with each selection (because of my print statement, I know that). But the same problem was occurring. If a letter was input instead of an integer right off the bat, it would throw an InputMismatchException. I have a feeling it has something to do with what is in the scanner. I've tried experimenting with "next(), nextLine(), nextInt(), equals()" and I've tried parsing with "Integer.valueOf()" trying to get the current line in the scanner to check it or parse it.

This leads me to my questions:

  1. Am I correct to assume that the scanner is reading the input and throwing the exception before I have a chance to catch it?
  2. How do I read the first line in the scanner at the beginning of the program in order to check if it is an integer or a String? I'm not a big fan of skipping the first line because then it causes the user to have to input their number twice in order for the program to print out a message such as:
Enter a number: 1
Enter a number: 1
Example one successful

Any input is greatly appreciated, thank you!


Solution

  • Question #1: no. The problem is, that the exception occurs in those lines which are not surrounded by try-catch (e. g. before the loop, in case 1 or case 2).

    Question #2: to read a line, use Scanner#nexLine(). There's no need to have the user to perform his input twice.

    Hint: write a method that requests an int value from the user and that returns only, if he entered a correct value.