CPSC 124 Introduction to Programming Spring 2024

Constructing Programs

We've seen several kinds of instructions - variable declarations, assignment statements, output, and (in the reading) input. But how do you come up with the right list of instructions to accomplish a particular task?

Several tactics:

The idea of patterns is that similar problems and tasks often have similar solutions, so if you can recognize a situation as one you've seen before, you can use what you know about the previous solution to help construct a solution for the current problem.

To illustrate this, consider the following example:

Write a road trip cost calculator program - it should prompt the user for the length of the trip, the cost of gas, and the car's miles per gallon and then compute and print how much will be spent on gas for the trip.

"Write a program" → start with the basic program structure:

    public class Progname {
      public static void main ( String[] args ) {
        statements
      }
    }
  

We've now already gone from one big problem (write a program to do something) to two smaller problems - figure out a good name (to replace Progname) and figure out the statements to carry out the task (to replace statements). Start with the easier problem: naming the program. The task is to compute the cost of gas, so a name reflecting that is a good choice:

    public class CostOfGas {
      public static void main ( String[] args ) {
        statements
      }
    }
  

At this point, the file can be saved with the name CostOfGas.java.

Replacing statements is a bigger task, but another pattern is useful here: programs that perform computations often consist of three main steps - get input, do the computation(s), produce output. We can replace statements with these steps, but since these steps are in English rather than Java, we will make them comments so the program can be compiled:

    public class CostOfGas {
      public static void main ( String[] args ) {
        // get trip length, price per gallon, car's mpg
        // compute trip cost
        // print trip cost
      }
    }
  

Observe that we've adapted the generic get input, do computation, produce output steps for this particular problem but that the framework is still there - the "get input" step for this program is to get the trip length, price per gallon, and mpg, the "do computation" step is to compute the trip cost, and so forth. You can also adapt the pattern as needed, for example, if the program works with hardcoded values, the "get input" step can be omitted.

Also observe that these three steps cover everything the program needs to do - while many details about how to do those steps are missing, the steps are complete because if they are accomplished, the program's task has been done.

Now we have three smaller tasks instead of one larger task - progress! Now utilize incremental development - instead of writing the entire program, tackle one of the smaller tasks at a time, testing the program after each piece. (If the smaller tasks are still largish, continue breaking things down into smaller pieces and implement those one at a time.)

But where to start? The statements are executed from first to last, so it makes sense to start with the first step - but it is also a good idea to start with the tasks that seem easier. (Perhaps you know what to do, or it's a smaller task.) In this case, let's start with "print trip cost" - output is System.out.println (or System.out.print), so we just have to figure out what to print. That's the trip cost...except that we don't know what this is yet because it hasn't been computed. The solution is to use a placeholder variable:

    public class CostOfGas {
      public static void main ( String[] args ) {
        // get trip length, price per gallon, car's mpg

        // compute trip cost

        // print trip cost
        System.out.println("trip cost: $"+tripcost);
      }
    }
  

If we assume that tripcost holds the cost of the trip, this will produce the correct output. However, this program won't compile - a variable needs to be declared and initialized in order to be used. Add those statements; since we haven't actually computed the trip cost yet, use a plausible value (the trip cost could be $20) that will be replaced later to initialize the variable.

    public class CostOfGas {
      public static void main ( String[] args ) {
        // get trip length, price per gallon, car's mpg

        // compute trip cost
        double tripcost = 20;    // ** placeholder!

        // print trip cost
        System.out.println("trip cost: $"+tripcost);
      }
    }
  

This program will compile, and can be run to verify that the output is formatted correctly.

The "print trip cost" step is now complete. Of the remaining steps, getting the input might be the most intimidating because it was in the reading but hasn't been discussed in class yet. So let's focus on computing the trip cost...but that needs the values that are supposed to come from the user, so again we turn to placeholder variables:

    public class CostOfGas {
      public static void main ( String[] args ) {

        // get trip length, price per gallon, car's mpg
        double price = 2.50;     // dollars per gallon  ** placeholder!
        double mpg = 40;         // ** placeholder!
        double triplength = 50;  // trip length, in miles  ** placeholder!
    
        // compute trip cost
        double tripcost = 20;    // ** placeholder!
    
        // print trip cost
        System.out.println("trip cost: $"+tripcost);
      }
    }
  

Now the trip cost placeholder can be replaced with the actual computation:

    public class CostOfGas {
      public static void main ( String[] args ) {

        // get trip length, price per gallon, car's mpg
        double price = 2.50;     // dollars per gallon  ** placeholder!
        double mpg = 40;         // ** placeholder!
        double triplength = 50;  // trip length, in miles  ** placeholder!
    
        // compute trip cost
        double tripcost = triplength/mpg*price;
    
        // print trip cost
        System.out.println("trip cost: $"+tripcost);
      }
    }
  

Finally, we need to tackle the input step in order to replace those placeholder values. The pattern for input using Scanner includes three steps: add the necessary import, create a Scanner to read input from the keyboard, and do the actual reading (print a prompt, read the value, store the value in a variable).

    import java.util.Scanner;
    
    public class CostOfGas {
      public static void main ( String[] args ) {

        // get trip length, price per gallon, car's mpg
        Scanner stdin = new Scanner(System.in);
    
        System.out.print("enter the price per gallon: $");
        double price = stdin.nextDouble();  // dollars per gallon

        System.out.print("enter the miles per gallon: ");
        double mpg = stdin.nextDouble();

        System.out.print("enter the length of the trip in miles: ");
        double triplength = stdin.nextDouble();  // trip length, in miles
    
        // compute trip cost
        double tripcost = triplength/mpg*price;
    
        // print trip cost
        System.out.println("trip cost: $"+tripcost);
      }
    }
  

Program complete! All three parts (get input, do computation, produce output) have been filled in, and everything in the original problem (write a program to print out how much you'll spend on gas if you drive home for the weekend) has been accomplished.