Search code examples
javaloopsvalidationintellij-idea

Loops and user input validation in java, again


So, I think about two days back I asked a question about input validation, and how to loop programs until the user gave a valid input..

So I made a calculator and I wanted to loop every step of the program so that if the user didn't put a double (69, 42.0) or the appropriate operator char (/, *, +, -) they would be stuck on that step till they got it right or otherwise closed the app entirely.

So one thing I got from the last question about this is that I could make a boolean value called "restart" or something and encapsulate my entire code except for the main method obviously and at the end I could make a question that they could answer true or false and the entire app could run again. While I admit having a "start over" button on my app is cool and useful for all my other a projects (probably not, I'm sure this can be done more efficiently), It still didn't satiate me and my original problem.

SO...

I got to trying everything I could (I know stack likes people who show that they at least tried).

EXAMPLE 1

Scanner input = new Scanner(System.in);

        double valX;
        
            System.out.println("Calculator Activated.");

                do
                {
                    System.out.print("Value X: ");
                    valX = input.nextDouble();
                }while (!input.hasNextDouble());
                {
                    System.out.println("Invalid number!");
                }
//Didn't work ¯\_(ツ)_/¯

EXAMPLE 2

Scanner input = new Scanner(System.in);

        double valX;

            System.out.println("Calculator Activated.");

            while (!input.hasNextDouble())
            {
                System.out.println("Value X: ");
                valX = input.nextDouble();
            }
//neither this one...

Note that the solution you guys give me has to apply to every step of the program.

And for a bit more clarity is the entire src code without the stuff I tried and the "restart" loop.

import java.util.Scanner;

public class CalTest
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);

        double valX, valY, divided, multiplied, added, subtracted;  //Declared all my variables...
        char operator;
        boolean restart; //Didn't need to declare it true or false since I'm using a Scanner anyway

        do //Start of the entire program
        {
            System.out.println("Calculator Activated.");

            System.out.print("Value X: "); //I need a loop here...
            valX = input.nextDouble();
            
            System.out.print("Operator: "); //And here...
            operator = input.next().charAt(0);

            System.out.print("Value Y: "); //And here too..
            valY = input.nextDouble();

            divided = valX / valY;
            multiplied = valX * valY;
            added = valX + valY;
            subtracted = valX - valY;

            if (operator == '/')
                System.out.println("Result: " + divided );
            else if (operator == '*')
                System.out.println("Result: " + multiplied); //<--Not sure if I need a loop with the if's
            else if (operator == '+')
                System.out.println("Result: " + added);
            else if (operator == '-')
                System.out.println("Result: " + subtracted);
            else
                System.out.println("Invalid operator!");

            System.out.print("Try again? "); //I also need a loop here, I think.
            restart = input.nextBoolean();

        } while (restart); //End of it if you declared false.
        
        System.out.println("Calculator terminated.");
    }
}

At one point I tried to use the same "restart the app" concept and made a boolean variable for every single step in the code and it honestly was tiresome and not worth it.


Solution

  • In your final code example in the class called CalTest where you assign valX = input.nextDouble(); you could a call recursive method that handles the exception until the input is what you want. Something like this:

    private static double getNextDouble(Scanner input) {
        try {
            return input.nextDouble();
        } catch (InputMismatchException e) {
            System.out.println("Value X must be a number: ");
            input.next();
            return getNextDouble(input);
        }
    }
    

    You'll replace valX = input.nextDouble(); with valX = getNextDouble(input);.

    You can tidy this up and make it work for your other potential error cases, perhaps creating a parameter for the output message and passing it in as an argument.