How to validate input in my Java program and add the option for the user to run the program again or exit it?

Viewed 284

So I have an assignment in my CISP 1 class that requires me to create a program that displays a bar chart comprised of asterisks based on the amount of sales 5 different stores have had. I've got a base made, but I still want to add a loop that validates the input from the user(i.e. throws an error when the user tries to enter a negative number), and I want to add the option to run the program or exit it. I'm just a little lost on how to do all of that, so I figured I'd reach out on this website and ask. I know a lot of this code could be simplified with arrays, but we haven't started studying that yet - so I'm afraid to be messing with something I don't fully understand. Below is my code:

import java.util.Scanner;

public class BarChart 

{
    public static void main(String[] args)

    {
        int store1, store2, store3, store4, store5;

        Scanner keyboard = new Scanner(System.in);

        System.out.println("This program will display a bar chart " + 
        " comprised of astericks based on five different stores' " +
        "sales. 1 asterick = $100 in sales.");

        System.out.print("Enter today's sales for store 1: ");
        store1 = keyboard.nextInt();

        System.out.print("Enter today's sales for store 2: ");
        store2 = keyboard.nextInt();

        System.out.print("Enter today's sales for store 3: ");
        store3 = keyboard.nextInt();

        System.out.print("Enter today's sales for store 4: ");
        store4 = keyboard.nextInt();

        System.out.print("Enter today's sales for store 5: ");
        store5 = keyboard.nextInt();

        System.out.println("Sales \t Bar Chart");
        System.out.println("----- \t ---------");

        System.out.print("\nStore 1: ");        
        
        for (int num = 0; num < store1; num += 100)
        {
            System.out.print("*");
            
        }

        System.out.print("\nStore 2: ");
        for (int num = 0; num < store2; num += 100)
        {
            System.out.print("*");
        }

        System.out.print("\nStore 3: ");
        for (int num = 0; num < store3; num += 100)
        {
            System.out.print("*");
        }

        System.out.print("\nStore 4: ");
        for (int num = 0; num < store4; num += 100)
        {
            System.out.print("*");
        }

        System.out.print("\nStore 5: ");
        for (int num = 0; num < store5; num += 100)
        {
            System.out.print("*");
        }

    }
    
}

I've tried adding if statements each time the user is asked to enter a sales amount, but that didn't work.

3 Answers
 Scanner keyboard = new Scanner(System.in); // initialize scanner  
 while (true) {  // infinite loop starts      
      <Do something...> // here you can do the things you need to do (e.g., change variables or record input)
      if (condition) { // condition for exiting the loop (e.g., input of positive number)
        break; // exiting infinite loop
      } // end of IF statement
    } // end of WHILE statement

You can use it as separate method and validate each input. It will not let the user to proceed until the valid value will be inputted.

I still want to add a loop that validates the input from the user(i.e. throws an error when the user tries to enter a negative number)

Here's a quick example that shows how to ask again when an invalind number is entered:

do {
    System.out.print("Enter today's sales for store 1: ");
    store1 = keyboard.nextInt();
    if (store<0) {
        System.out.println("Sales must be non-negative!");
    }
while (store<0);

I want to add the option to run the program or exit it.

This would be similar to the do { ... } while( ... ); above except you'd put the whole program from below the Scanner line inside the body of the do loop. Then you just ask at the bottom if they want to start over and write your conditional statement in the while portion appropriately.

pls take the time to read through

Solution to the problem

do-while loop

What you're looking for is a while loop that this answer suggests, however you can specify whether to force the user to retry, or break the program and throw an error.

If you'd like to make the user retry and not throw an error that makes the program break, possibly with a retry message every time the user inputs negative numbers, you can use a do-while loop. The do-while loop will execute as "do this then check" rather than the while loop being "check than do this" (you can ensure that your code is more concise this way). The do-while loop version:

int input;  // Declare the variable to be initialized inside the do {} block.
int storeSales;                      // You can just relax and declare here.
do {                                 // This is the start of the do-while loop
    System.out.print("...");         // Your prompt goes here
    storeSales = scanner.nextInt();  // Grabbing input from the user
    if (storeSales < 0) {            // Checking if the input is smaller than 0
        System.out.print("...");     // Your message when input is invalid
    }
} while (storeSales < 0);            // The condition goes here

The caveat of the do-while loop for situations like this is for having conditions in the while loop that the do block will be always executed at least once, requires a variable that isn't initialized first but initialized in the loop itself. Initializing a "user input" variable but then giving it a value of "value that makes a statement work" makes the code awkward and dirty.

while loop

The while loop version will look like this:

int storeSales = -1;  // You have to initialize first here, since the while is checked first.
while (storeSales < 0) {  // Awkward!
    System.out.print("");           // Your prompt goes here
    storeSales = scanner.nextInt(); // Grabbing input from the user
    if (storeSales < 0) {           // Checking if the input is smaller than 0
        System.out.print("");       // Your message when input is invalid
    }
}

Exceptions

If instead, you'd like to break the program when the input is invalid (smaller than 0): Introducing the throw statement: Try this code out:

public class BarChart {
    public static void main(String[] args) {
        System.out.println(5 / 0);
    }
}

You'll yell at me: WTF is this, you're making a program that throws ArithmeticException runtime exception! Division by 0 doesn't make sense!

Well, that's the point. Exceptions in Java are those that happen during runtime because of some condition that doesn't have to do with syntax, clear mistakes like String x = 0, etc. That's the kind of exception you're looking for. To throw such an error similar to the example above , use the throw statement and don't use a loop:

int storeSales = scanner.nextInt();
if (storeSales < 0) {
    // Since the exception is related to math, you can use something like ArithmeticException. Your choice though.
    throw new ArithmeticException();  // An exception is also an object, so you initialize it that way.
}

CAVEAT, Java doesn't expect exceptions in the first place, and so you have to declare that your method throws exceptions. Even main(). And when you call OTHER methods that ALSO have exceptions, you either have to handle them with a try-catch block, or leave it and add the exceptions to the method definition. But that's for another day I guess.

General improvements

You're doing the same thing, same code, same names (essentially), same print() statements a hard-coded 5 times! You can use a for loop. Unless your names have to be unique and declared separately (which I digress, you names are literally store1, store2, store3, etc.) you can just use a general, reinitialized variable name in every iteration of the for loop.

You can also scan the user input about how many stores (instead of hard-coding 5) to show the data, to make the program completely soft-coded and dynamic (The assignment probably doesn't require you this, refactor the code to your needs)

This code below will be grabbing the user input, then printing it out INSTANTLY AFTER. Now that I look at your solution, maybe it was right after all to define separate variables instead of putting the input in an array, since you want all the input at once then print everything at once. Here's how it goes:

// You'd want to reformat the code to your preference.
import java.util.Scanner;
public class BarChart {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int storeCount = scanner.nextInt();
        for (int i = 0; i < storeCount; i++) {  // A loop that repeats 5 times.
            // Choose one of the three solutions above and insert them here, I choose the do-while since it's the cleanest
            int storeSales;
            do {
                // You can "concatenate" strings (numbers becomes themselves but in text)
                System.out.print("Enter today's sales for store " + (i + 1) + ": ");
                storeSales = scanner.nextInt();
                if (storeSales < 0) {
                    System.out.print("Sales cannot be negative, please try again");
                }
            } while (storeSales < 0);
            // Now that the storeSales value has been definitely initialized (or you chose the exceptions solution, I don't blame you) the printing goes here.
            System.out.println("Store " + (i + 1) + "'s sales:");
            for (int j = 0; j < storeSales; j += 100) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

There's not much to do with your code otherwise, since without the use of arrays, the best you can do is define separate variables, then having a method or two (a reusable piece of code with a name) to do the inputting and printing job for you to make the code cleaner and less repetitive.

In the end, just choose one of the three solutions and apply them to each of your variables. Your code is quite good (if it's intended this way). CHEERS!

oh my god someone read till the end of the post i love you

Related