5.7.2. The American Structure Example

Time: 00:04:46 | Download: Large Small | Streaming
Review

Our familiarity with time is a significant advantage of the Time structure example, allowing us to focus more on structures and less on the illustrating problem. But, basing the example on time also presents a disadvantage: What does the "60" appearing in make_time(int s) and add mean? There are 60 seconds in a minute and 60 minutes in an hour. But, it isn't clear from a casual examination of the functions which "60" they use. While it doesn't make a difference in the Time example, it does when the unit numbers differ.

The U.S. is the only industrialized nation not using the metric system in its commercial and day-to-day activities. Instead, it uses the "United States customary system." In this system

  • 1 tablespoon (Tbsp) = 3 teaspoons (tsp)
  • 1 fluid ounce (fl-oz) = 2 tablespoons (Tbsp)
  • So, 1 ounce = 2 tablespoons = 6 teaspoons
A picture showing one large rectangle representing fl-oz; two medium sized rectangles representing Tbsps; and size small rectangles representing tsps.
U.S. customary system volume measures. The relationship between the three volume units appearing in the problem.
We can represent a total volume with a structure1 just as we did in the Time example. However, the relationships between the units make understanding the numbers in the resulting program easier.

The American Volume Problem

Write a C++ program in three files

  1. American.h: contains a structure specification and function prototypes
  2. American.cpp: contains the structure functions
  3. driver.cpp: code to test the American structure and functions (main will be in this file)

Create a structure named American with three fields to represent liquid measures using the U.S. customary units:

  1. ounce
  2. tablesp
  3. teasp
  4. The structure does not need to handle fractional values for any of the units (i.e., make the fields integers)

The program must have the following structure functions:

  1. Two functions to make an instance of the American structure
    1. American make_American(int oz, int Tbsp, int tsp);
    2. American make_American(int tsp);
  2. add
    1. has two American objects parameters
    2. sums the objects without changing either one
    3. returns a new, normalized American object to represent the sum
    4. normalization means
      • 0 ≤ teasp < 3; 3 teaspoons should "carry" to make a tablespoon
      • 0 ≤ tablesp < 2; 2 tablespoons should "carry" to make a fluid-ounce
    5. the add function may not use branch or loop statements
  3. print
    1. has a single American object parameter
    2. prints the objects in this format: 3 fl-oz, 1 Tbsp, 2 tsp

The program must have a driver testing all the structure functions.

Unit Analysis

Mathematicians might use raw numbers when solving some problems, but engineers and scientists always attach units to numbers. For example, 5 inches is quite different than 5 light-years. We can perform arithmetic operations on the units in the same way as numbers and variables, which is especially helpful for multiplication and division. Carrying the units through the algebraic operations solving a problem can help us avoid some errors. In the American structure problem, arranging the equalities I, II, and III so that the units cancel2 out helps us identify and understand the numbers used in the following program.

Converting An Integer To An American Structure

(a) x Tbsp / 3 = (x tsp) (1 Tbsp / 3 tsp). The tsp units cancel out, leaving x Tbsp / 6.
(b) x fl-oz / 6 = (x tsp) (1 Tbsp / 3 tsp) (1 fl-oz / 2 Tbsp). The tsp and Tbsp units cancel out, leaving x fl-oz / 6.
(c)
temp.ounce = x / 6;	// each group of 6 tsp = 1 ounce
x %= 6;			// the remaining tsp that didn't fit in an ounce
temp.tablesp = x / 3;	// each group of 3 Tbsp = 1 ounce
temp.tsp = x % 3;	// the remaining Tbsp that didn't fit in an ounce
Converting tablespoons and teaspoons to fluid onces.
  1. We use Figure 1, equality I, to convert from teaspoons to tablespoons. We begin with x tsp, and our target is Tbsp. So, we arrange equality I so that the tsp units cancel2.
  2. Similarly, we use Figure 1, equality III, to convert from teaspoons to fluid ounces. We begin with x tsp, and our target is fl-oz. So, we arrange III so that the tsp and Tbsp units cancel2.
  3. Converting an integer to an American structure takes several statements (most of the second overloaded make_American function). The added complexity results from the requirement of saving each field as a whole number. temp is an American structure object, and x, the function parameter, is the number of teaspoons that the functions convert to an American structure.

Converting An American Structure To A Single Integer

(a) 3x tsp = (x Tbsp) (3 tsp / Tbsp). The Tbsp units cancel out, leaving 3x tsp.
(b) 6x tsp = (x fl-oz) * (2 Tbsp / fl-oz) (3 tsp / Tbsp). The Tbspand fl-oz units cancel out, leaving 6x tsp.
(c)
int i1 = am1.ounce * 6 + am1.tablesp * 3 + am1.teasp;
Converting fluid onces and tablespoons to teaspoons.
  1. Again, we use Figure 1, equality I, to perform the needed conversion operation, but we convert from tablespoons to teaspoons this time. We begin with x Tbsp, and our target is tsp. So, we arrange equality I so that the Tbsp units cancel2.
  2. Following the pattern of the previous figure, we use Figure 1, equality III, to convert fluid ounces to teaspoons. We begin with x fl-oz, and our target is tsp. So, we arrange III so that the fl-oz and Tbsp units cancel2.
  3. A statement, based on the derived conversion operations, converting an American structure object, am1, to an integer, i1.

American Program Listings

struct American
{
	int	ounce;
	int	tablesp;
	int	teasp;
};

// function declarations or prototypes
American make_American(int oz, int Tbsp, int tsp);
American make_American(int tsp);
American add(American am1, American am2);
void print(American am);
American.h. The American structure specification and function prototypes. The prototypes "use" the name American as a data type, so they must follow the structure specification.
#include <iostream>
#include "American.h"
using namespace std;

American make_American(int oz, int Tbsp, int tsp)
{
	American temp;

	temp.ounce = oz;
	temp.tablesp = Tbsp;
	temp.teasp = tsp;

	return temp;
}


American make_American(int tsp)					// See Figure 2
{
	American temp;

	temp.ounce = tsp / 6;
	tsp %= 6;
	temp.tablesp = tsp / 3;
	temp.teasp = tsp % 3;

	return temp;
}

American add(American am1, American am2)			// See Figure 3
{
	int	i1 = am1.ounce * 6 + am1.tablesp * 3 + am1.teasp;
	int	i2 = am2.ounce * 6 + am2.tablesp * 3 + am2.teasp;

	return make_American(i1 + i2);
}

void print(American am)
{
	cout << am.ounce << " fl-oz, " << am.tablesp << " Tbsp, "
		<< am.teasp << " tsp" << endl;
}
American.cpp. The American function definitions. The two make_American functions are overloaded. The first converts three integers into an American object; the second converts a single integer into an American object. The add function converts two American objects into integers, sums them, and creates a new American structure representing the sum. The print function prints an American object to the console.
#include "American.h"

int main()
{
	American	am1 = make_American(3, 1, 2);
	American	am2 = make_American(9);

	American	am3 = add(am1, am2);
	print(am3);

	return 0;
}
driver.cpp. The driver completes the program and tests the functions in American.cpp.

  1. Typically, the U.S. system represents measurements with a single value in one unit rather than multiple values with different units. So, for example, a recipe would require 11 tsp of an ingredient, not 1 fl-oz, 1 Tbsp, and 2 tsp.
  2. "Canceling" is a shorthand term for dividing a number, variable, or unit by itself. For example, tsp / tsp = 1. In general, we can say x / x = 1; x ≠ 0.