Overview of This Lesson

Sometimes a program's decision making needs to be a little bit more complex. For example, you might have a switch statement that determines the maximum number of days in a month, but for February, you'll also have to check for leap years. The case for February would there for need a conditional or if/else to return either 28 or 29 days, depending on the year.

You can nest any kind of selection structure into the body of any other selection structure: The else block of an if-else could contain a multi-sided if, or the if-block of a multi-sided if could contain a switch statement, for example. In this lesson we'll do some examples of nested selection structures.

Pre-Requisites

Before doing this lesson, make sure you've gone over the If Statements tutorial and the Switch Statement tutorial.

Nested Selections

Imagine a situation where you ask the user for a log-in name. If they enter a valid name, ask them for a password. If the password is valid, display a message on the screen. If either the password or login name is not valid, display a specific message to the user. For this we might want to have selection structures nested inside other selection structures.

To perform this task, you will first need an if statement to check the log-in name and possibly display a message if it's invalid:

import java.util.Scanner;
public class Nested {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String name = in.nextLine();

        if (name.equals("Artemesia")) {

            // check password

        } else {
            System.out.println("Invalid Login Name");
        }
    }
}

Next, we can add another if statement inside the if-block to test the password:

import java.util.Scanner;

public class Nested {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String name = in.nextLine();

        if (name.equals("Artemesia")) {

            // check password
            System.out.print("Enter your password: ");
            String pass = in.next();

            if (pass.equals("chicken")) {
                System.out.println("Welcome to Arti's Cat House!");
            } else {
                System.out.println("Invalid password.");
            }

        } else {
            System.out.println("Invalid Login Name");
        }
    }
}

Be careful when working with nested if's that have no braces. To see why, examine the following code:

public class IfThing {
    public static void main(String[] args) {
        int x = 5;
        int y = 10;
        if (x < 2)
             if (y > 5)
                System.out.println("Meow");
        else
             System.out.println("hi");
        System.out.println("bye");
    }
}

What do you think the output will be? Run the program - what is the output you actually get? Why?

In this example, the else-block appears to belong to the top if statement. However, without the braces, an else-block will always belong to the if-statement directly above it. In this case, the else-block actually belongs to the if (y > 5) statement. When working with nested Ifs, it's best to use braces to avoid such confusion.

Nesting vs. Stacking

Don't confuse nesting if-statements with stacking if-statements. Nesting occurs when an if-statement appears inside the block or body of another if:

String paymentLate = "";
double penalty = 0;
if ( (month <= 12) && (month >= 1) ) {
    if ( (day >= 1) && (day <= MAX_PAY_DATE) ) {
        paymentLate = "Payment is on time.";
    } else {
        paymentLate = "Payment is late.";
        penalty = (day - MAX_PAY_DATE) * PENALTY;
    }
} else {
    System.out.println("Invalid month number!");
}

In the above example, the if-statement checking the day variable is nested inside the if-statement checking the month variable.

The example below does not nest if-statements; it stacks them on top of one another:

if (age >= 65) {
    discount = .1;
} else {
    discount = 0;
}
if (memberStatus == 2) {
    shippingCost *= .5;
}

Exercises

  1. What is the output of each of the following code segments? After determining the output, fix the indentation:
    1. int x = 5;
        int y = 10;
        int z = 2;
        if (x > y) {
        System.out.println("twice x is " + (x * 2));
        if (x * z == y) {
        System.out.println("xz equals y");
        }
        } else {
        System.out.println(y /= z);
        }
    2. int x = 5;
        int y = 10;
        int z = 2;
        if (x > y) {
        System.out.println("twice x is " + (x * 2));
        }
        if (x * z == y) {
        System.out.println("xz equals y");
        } else {
        System.out.println(y /= z);
        }
  2. A program at a video store calculates the cost of renting a certain number of DVD's. Some members have purchased a special Rewards Program membership that allows them to rent DVDs for only $3.59 per DVD. For all other customers, DVD rentals are $4.99 per DVD unless they rent more than 4 DVDs at one time, in which case the cost per DVD rental is $3.99. Write the part of the program that calculates the sub total before taxes.

    With this kind of problem, a decision table might be helpful (if you haven't done decision tables in logic class, then don't worry about this):

    Charge per Rental 1 2 3
    Number of Rentals  -- <=4  >4
    Rewards Program? Y N N
    $4.99 per Rental X
    $3.99 per Rental X
    $3.59 per Rental X

    What if the psuedocode for this problem was written as:

    Print "Enter number of DVDs:"
      Get numDvds
      Print "Is customer in Rewards Program?"
      Get rewardsMember
      If rewardsMember = "Y" Then
          subTotal = numDVDs * 3.59;
      End If
      If numDvds <= 4 Then
          subTotal = numDvds * 4.99;
      Else
          subTotal = numDvds * 3.99;
      End If
      Print "Sub Total: ", subTotal

    What is the output when the user enters 5 DVDs and "Y" for the Rewards Program?

    The problem with this code is that even though we calculate the correct sub total when we evaluate that rewardsMember = "Y" is true, we later encounter a true condition for "numDvds > 4", which resets the sub total to numDvds * 3.99. This would output 19.95 instead of the correct result 17.95!

    Write this program correctly!

  3. The decision table below shows the Residence Assignment policy for a local university:
    Residence Assignment Rules
    1 2 3
    Student Age <21 <21 >=21
    Residence Type Co-Ed Non Co-Ed --
    Residence Assigned Trudeau MacDonald Laurier

    Write a program that prompts the user to enter the student's age and whether or not the student wants a co-ed dorm room. Then display the student's residence hall on the screen using the criteria in the table. Write the most efficient code possible.

  4. The decision table below shows the Medical Insurance Policy that defines how much of a reimbursement patients receive:

    Medical Insurance Policy Rules
    1 2 3 4
    Deductible Status Met Met Met Not Met
    Type of visit Doctor Hospital Lab --
    Amt. of Reimbursement 50% 80% 70% 0%

    Write a program that prompts the user to enter the total amount due for the medical visit, then find out if the client has paid the deductible. If they have, then ask the user which type of visit the client had. Display the appropriate reimbursement amount percentage based on the table. Write the most efficient code possible

  5. Write a program that validates a date entered by the user. The user will enter a month number and then a day number. Your program should display a message, "Invalid date!" if the date is not valid. e.g. if the inputs are 2 and 30 (30th of February) or the inputs are 6 and 31 (31st of June) then message should appear. If a date is valid, display the message "This is a valid date." For now, assume Feb 29 is invalid. BONUS: in addition, as for the year and include leap years.

1. What is the output of each of the following code segments:

a)

int x = 5;
int y = 10;
int z = 2;
if (x > y) {
    System.out.println("twice x is " + (x * 2));
    if (x * z == y) {
        System.out.println("xz equals y");
    }
} else {
    System.out.println(y /= z);
}

5
(the first condition x > z is false, therefore it jumps to that if's matching else block and prints y /= z)

b)

int x = 5;
int y = 10;
int z = 2;
if (x > y) {
    System.out.println("twice x is " + (x * 2));
}
if (x * z == y) {
    System.out.println("xz equals y");
} else {
    System.out.println(y /= z);
}

xz equals y
(the braces have moved around in this question: the if (x * z == y) is no longer inside the if (x > y) block, so it's evaluated regardless of the truth value of x > y)

Question 2:

ERROR NOTE: DISC_COST should be initialized to 4.99 and REG_COST should be initialized to 3.99.

question 2 solution
Question 2. dvd rentals

Question 3:

question 3 solution
Question 3. student residence

Question 4:

question 4 solution
Question 4. medical fee reimbursement

Question 5:

question 5 solution part a question 5 solution part b
Question 5. date validation