0

I'm working on a project that calculates the value of a bank account based on starting balance(b), interest rate(IR), and quarters to display. My entire code works perfectly, but the very last portion is to make sure the variables like interest rate are within the confines of the boundaries my professor gave me. I do need to display an error message if the user enters a value outside the boundaries and ask for the value again.

For example, the number of quarters to display needs to be greater than zero, and less or equal to 10.

As you can see, pretty much all of my program is in a do-while loop. I know I can have nested loops, but what would I be able to put in my do-while loop that would work in this situation? An if-else statement? Try and catch block? Another while loop?

If I used a try-catch, then could anyone give me an example of how I could do that? Thank you very much for your time, and all help is appreciated! The below is my code for reference.

    import java.util.Scanner;

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


   Scanner input = new Scanner(System.in);

   int quartersDisplayed;
   double b, IR;


    do
  {
     Scanner keyboard=new Scanner(System.in);
     System.out.println("Enter the numbers of quarters you wish to display that is greater than zero and less or equal to 10: ");
     quartersDisplayed = keyboard.nextInt();

     System.out.println("Next enter the starting balance. ");
     System.out.println("This input must be greater than zero: ");
     b = keyboard.nextDouble();


     System.out.println("Finally, enter the interest rate ");
     System.out.println("which must be greater than zero and less than or equal to twenty percent: ");
     IR = keyboard.nextDouble();


     System.out.println("You have entered the following amount of quarters: " + quartersDisplayed);         
     System.out.println("You also entered the starting balance of: " + b);
     System.out.println("Finally, you entered the following of interest rate: " + IR);
     System.out.println("If this information is not correct, please exit the program and enter the correct information.");


     double quarterlyEndingBalance = b + (b * IR/100 * .25);
     System.out.println("Your ending balance for your quarters is " + quarterlyEndingBalance);  
     System.out.println("Do you want to continue?"); 
     String yes=keyboard.next("yes");
     if (yes.equals(yes))
     continue;
     else
     break;

        }
        while(true);
  }
}
weston
  • 51,132
  • 20
  • 132
  • 192
J. Nav
  • 55
  • 1
  • 8
  • In order to run this loop forever you need to avoid exit the do-while loop, basically you need to handle exception within. That means you need to have try-catch block which catch all the possible exceptions. – Eranda Oct 10 '16 at 02:52
  • @Gendarme It's related because I believe I need an exception thread. – J. Nav Oct 10 '16 at 02:54
  • Check this out http://stackoverflow.com/a/39882790/360211 – weston Oct 10 '16 at 02:56
  • @Eranda So I just do one huge try-catch block? Where would you recommend I put it? Maybe right before my formula and after all my variable declarations and stuff? – J. Nav Oct 10 '16 at 02:56
  • @weston Thank you! That does help, but how would I put in multiple exceptions (conditionals) in a single try-catch block? – J. Nav Oct 10 '16 at 02:58
  • @J.Nav It shouldn't be a big try catch block, you can handle each case by case. But the ultimate goal should be catching the exception within the block. try { //code throws exception AException and BException } catch (AException e) { } catch (BException e) { } or try { //Code throw AException } catch(AException e) { } try { //Code throw BException } catch(BException e) { } – Eranda Oct 10 '16 at 02:59
  • I don't know why you would need that. – weston Oct 10 '16 at 02:59
  • All three of my variables have specific conditionals. So what you guys are saying is have a try-catch block for each variable. So would it look like: 'try{ System.out.print(prompt) return sc.nextDouble(); } catch (InputMismatchException e1) { System.out.println("Error. Please enter a value that meets the boundaries");' – J. Nav Oct 10 '16 at 03:00
  • Try-catch should be used only if an exception would be thrown. Not if your arbitrary conditions aren't met. For example, if you're doing `nextInt()` and there's a possibility that there's a character instead, an exception will be thrown and your program will terminate. – RaminS Oct 10 '16 at 03:01
  • I was suggesting a using a function, then calling that function multiple times. – weston Oct 10 '16 at 03:03
  • @Gendarme So use something else if, for example, the user enters 20 quarters instead of the 0->10 conditional? – J. Nav Oct 10 '16 at 03:03
  • I am writing an answer, trying to cover everything, but it's slightly awkward coding on StackOverflow, so it might take a little while. – RaminS Oct 10 '16 at 03:05
  • @weston What you're saying makes a lot of sense and helps. I get what you're saying now. Using the format of the link you sent me, could you give me a basic skeleton of what my code should look like? You have a String description. For me, would that String be the conditional for the variable I'm using the try-catch block on? Also, could you tell me what your 'return sc.nextDouble();' does? – J. Nav Oct 10 '16 at 03:09

3 Answers3

1

So here's some code to answer your questions and help get you started. However, there are problems with your logic that do not pertain to your question which I will address afterward.

Note: I have added comments to your code. Most of them start with "EDIT:" so that you can tell what I changed. I didn't use this prefix in all cases because some of it is new code and it's obviously my comment

import java.util.Scanner;

public class InterestCalculator {

public static void main(String[] args) {
//      EDIT: you already have a scanner defined below with a more meaningful name so I removed this one
//      Scanner scannerObject = new Scanner(System.in);

        Scanner input = new Scanner(System.in);

        //EDIT: defining userResponse outside the loop so we can use it everywhere inside
        String userResponse = null;

        do {
            //EDIT: moved the variables inside the loop so that they are reset each time we start over.
            //EDIT: initialize your variable to a value that is invalid so that you can tell if it has been set or not.
            int quartersDisplayed = -1;
            //EDIT: gave your variables more meaningful names that conform to java standards
            double startingBalance = -1, interestRate = -1;

            //EDIT: you don't need a second Scanner, just use the one you already have.
//          Scanner keyboard = new Scanner(System.in);

            do{
                System.out.println("Enter the numbers of quarters you wish to display that is greater than zero and less or equal to 10: ");
                userResponse  = input.next();
                try{
                    quartersDisplayed = Integer.parseInt(userResponse);
                }catch(NumberFormatException e){
                    //nothing to do here, error message handled below.
                }
                if(quartersDisplayed <= 0 || quartersDisplayed > 10){
                    System.out.println("Sorry, that value is not valid.");
                }else{
                    break;
                }
            }while(true);


            do{
                System.out.println("Enter the starting balance (must be greater than zero): ");
                userResponse  = input.next();
                try{
                    startingBalance = Double.parseDouble(userResponse);
                }catch(NumberFormatException e){
                    //nothing to do here, error message handled below.
                }
                if(startingBalance <= 0){
                    System.out.println("Sorry, that value is not valid.");
                }else{
                    break;
                }
            }while(true);


            do{
                System.out.println("Enter the interest rate (greater than zero less than twenty percent): ");
                userResponse  = input.next();
                try{
                    interestRate = Double.parseDouble(userResponse);
                }catch(NumberFormatException e){
                    //nothing to do here, error message handled below.
                }
                //Note: I assume twenty percent is represented as 20.0 here
                if(interestRate <= 0 || interestRate > 20){
                    System.out.println("Sorry, that value is not valid.");
                }else{
                    break;
                }
            }while(true);


            System.out.println("You have entered the following amount of quarters: "
                            + quartersDisplayed);
            System.out.println("You also entered the starting balance of: " + startingBalance);
            System.out.println("Finally, you entered the following of interest rate: "
                            + interestRate);
            System.out.println("If this information is not correct, please exit the program and enter the correct information.");

            double quarterlyEndingBalance = startingBalance + (startingBalance * interestRate / 100 * .25);
            System.out.println("Your ending balance for your quarters is "
                    + quarterlyEndingBalance);
            System.out.println("Do you want to continue?");
            //EDIT: modified your variable name to be more meaningful since the user's response doesn't have to "yes" necessarily
            userResponse = input.next();
//          EDIT: modified the logic here to compare with "yes" or "y" case insensitively.
//          if (userResponse.equals(userResponse))
            if("y".equalsIgnoreCase(userResponse) || "yes".equalsIgnoreCase(userResponse))
                continue;
            else
                break;

        } while (true);

Now to address other issues - your interest calculation doesn't seem correct to me. Your formula does not make use of the quartersDisplayed variable at all. I assume you're compounding the interest quarterly so you will definitely need to make use of this when calculating your results.

This may be beyond the scope of your project, but you should not use double or float data types to represent money. There is a stackoverflow question about this topic that has good information.

Possible improvements - since you're asking the user for two values of type double you could create a method to ask for a double value and call it twice instead of repeating the code. This is a better approach because it helps reduce the chance of mistakes and makes testing and maintenance easier.

Community
  • 1
  • 1
D.B.
  • 4,016
  • 2
  • 15
  • 35
  • This works absolutely brilliantly! Thank you for taking the time to do this. Your variable names were EXACTLY like mine, but I changed them because the formula my professor gave me had "b" and "IR" as the variable names, and I was unsure as to if I could change them. He clearly says, b is the starting balance and IR is the interest rate. So I don't know. – J. Nav Oct 10 '16 at 03:29
  • I would hope your professor would appreciate the need for meaningful variable names. I doubt you would be marked down for having code that is **more** readable. – D.B. Oct 10 '16 at 03:32
  • So when you initialized the variables to an invalid value, and then put 'String userResponse = null', does that make sure that the user input, if invalid, will give the error message and not work? Also, I've seen on here, but not in my book, the while(true). What exactly does it do and why is it necessary? Finally, how, at the very end, did you make sure if the user input "no" to "Do you want to continue", then the program would end? – J. Nav Oct 10 '16 at 03:32
  • Some small mistakes: `startingBalance < 0` should be `startingBalance <= 0`. Same goes for `interestRate`. – RaminS Oct 10 '16 at 03:32
  • You guys are awesome. And @D.B., yes I would hope he would too. It confused me at first when I saw b and IR, because it didn't seem to fit JAVA standards, like you said. – J. Nav Oct 10 '16 at 03:37
  • @J.Nav actually no the initialization to null does not help with displaying the error message. If we needed a `String` value it could, but since we need a `int` and `double` the part that you should focus on is the `Integer.parseInt` and `Double.parseDouble`. We parse the `String` we got from the user and see if it is a valid integer or double. If it is not then a `NumberFormatException` is thrown and our `int` or `double` variable is not updated. Since the value is initially invalid it will fail our validation logic. Now that I think about it I need to edit the code again to move those. – D.B. Oct 10 '16 at 03:40
  • @J.Nav `while(true)` just loops forever until you're ready to exit. It allows you to continue indefinitely until a condition is met. It is necessary in this case because I wanted to make the output look prettier. If the boundary condition is part of the loop you display the error message incorrectly. I just wanted to avoid repeating code as much as I could. – D.B. Oct 10 '16 at 03:47
  • @J.Nav finally to your last question above, I did not write any condition for no, I wrote a condition for yes and anything other than the values we expect for yes results in breaking out of the loop. – D.B. Oct 10 '16 at 03:49
  • Thank you for taking time to explain. This does help. – J. Nav Oct 10 '16 at 03:50
0

You can do something like this in your do/while loop:

do
{
    Scanner keyboard = new Scanner(System.in);

    do
    {
        System.out.println("Enter the numbers of quarters you wish to display that is greater than zero and less or equal to 10: ");
        quartersDisplayed = keyboard.nextInt();
    }
    while (quartersDisplayed < 1 || quartersDisplayed > 10);

    System.out.println("Next enter the starting balance. ");
    do
    {
        System.out.println("This input must be greater than zero: ");
        b = keyboard.nextDouble();
    }
    while (b < 1);

    // rest of code ... 
}
Michael Markidis
  • 4,093
  • 1
  • 11
  • 21
  • Would I need a break in there somewhere? After ' while (b < 1); ' ? – J. Nav Oct 10 '16 at 03:13
  • @J.Nav You would just have the rest of your code. I just put the first two capture cases for a starting example. You can also catch a bad format exception in the inner do while loops in case the user enters bad data. – Michael Markidis Oct 10 '16 at 03:15
  • Thank you very much for your help! I'll definitely try this out as well as the try-catch block and see what works best. This will be my first time working with a nested loop so I'm pretty excited! – J. Nav Oct 10 '16 at 03:17
  • The loop does work, I just need an error message. Thanks again! – J. Nav Oct 10 '16 at 03:21
  • @J.Nav No problem. – Michael Markidis Oct 10 '16 at 03:23
  • If you enter a completely wrong value such as 'X' the code throws an exception. – D.B. Oct 10 '16 at 03:24
  • Don't forget that `b` is a `double`. It can be less than 1 even though it's greater than 0. – RaminS Oct 10 '16 at 03:25
  • @D.B. I know that. I stated in my comment that he can put in the try/catch within the do/while. – Michael Markidis Oct 10 '16 at 03:26
  • @MichaelMarkidis yes, but I'm pretty sure that will cause an infinite loop. Please correct me if there's a way to do it using `nextInt` that does not cause an infinite loop. – D.B. Oct 10 '16 at 03:28
  • @D.B. You are probably right. My intent was not to give the OP the entire answer, but rather to get him going in the right direction. Giving the whole answer will not allow the OP to learn. – Michael Markidis Oct 10 '16 at 03:30
0

With the Scanner#hasNextInt (and the equivalent for double), you can avoid having exceptions thrown, and thus don't need try-catch clauses. I think in general if you can avoid try-catch, it's good, because they are clumsy - but I might be wrong.

However, my approach is like this. Inside your outer do-while, have three other do-while-loops to get the three values. The reason is that you want to keep looping until you get a correct value. The explanation of why keyboard.nextLine() is important is covered here.

I didn't include all of your code, only the part in question. Here's my take on it:

import java.util.Scanner;

public class InterestCalculator {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int quartersDisplayed = -1;
        double b = -1.0;
        double IR = -1.0;

        do {
            do {
                System.out.println("Enter the number of quarters.");
                if(keyboard.hasNextInt()) {
                    quartersDisplayed = keyboard.nextInt();
                    keyboard.nextLine(); //important
                } else {
                    System.out.println("You need to enter an integer.");
                    continue;
                }
            } while(quartersDisplayed < 1 || quartersDisplayed > 10);

            do {
                System.out.println("Enter the starting balance.");
                if(keyboard.hasNextDouble()) {
                    b = keyboard.nextDouble();
                    keyboard.nextLine();
                } else {
                    System.out.println("You must enter a number.");
                    continue;
                }
            } while(b <= 0);

            do {
                System.out.println("Enter the interest rate.");
                if(keyboard.hasNextDouble()) {
                    IR = keyboard.nextDouble();
                    keyboard.nextLine();
                } else {
                    System.out.println("You must enter a number.");
                    continue;
                }
            } while(IR <= 0 || IR > 20.0);

            //... rest of code
        } while(true);
    }
}
Community
  • 1
  • 1
RaminS
  • 2,151
  • 3
  • 19
  • 29
  • Thank you, this is actually really cool. I'm brand new to programming, but I'm finding it (while stressful) pretty fun. Could you please explain to me why try-catch blocks can be clumsy, and are there any times you would definitely not use one? – J. Nav Oct 10 '16 at 03:39
  • @J.Nav If you can use a simple method like `hasNextInt()` and get rid of try-catch, I think it's much better because the code becomes more readable, and this is of highest priority when writing programs. Exceptions aren't really made to be used to control the flow of the program - they are more or less errors, and if you can you should probably avoid getting them. Here's a post about precisely this: [Why not use exceptions as regular flow of control?](http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control/). – RaminS Oct 10 '16 at 03:47