Main

February 06, 2004 (Friday)

Chapter 2: Looping and counting

This chapter is fairly straightforward. You should already be familiar with most of the concepts presented. Some of the more subtle issues are presented in more detail after the program below. The topics in the chapter that you should already know from your Java background and the C lectures are:

We will not be discussing the above ideas in class. Consult the text if you are unfamiliar with these language features -- they are pretty much the same for Java, C and C++.

This chapter also introduces the concept of a loop invariant (K&M § 2.3.2). This concept can be quite useful when designing while loops for example, and can help reduce or eliminate subtle off-by-one errors which can cause severe problems in programs. We won't be talking too much about loop invariants in class -- the presentation in the textbook is quite clear.

There is a precedence table on page 32. Don't feel obligated to memorize it. Refer to it when you are in doubt about the order of execution of various operators. (Incidentally, K&R also have a precedence table on page 53).

Chapter 2 describes the implementation of the following program which, like Chapter 1, displays a frame around a greeting, except that the code is a bit more flexible in that an arbitrary number of padding spaces can be defined between the greeting and the border. We can change how much padding occurs by changing the initialization of the pad constant and recompiling and rerunning the program. The asterisks and spaces that comprise the output are displayed one at a time (instead of as strings, which was how they were displayed in Chapter 1).

#include <iostream>
#include <string>

// say what standard-library names we use
using std::cin;         using std::endl;
using std::cout;        using std::string;


int main()
{
	// ask for the person's name
	cout << "Please enter your first name: ";

	// read the name
	string name;
	cin >> name;

	// build the message that we intend to write
	const string greeting = "Hello, " + name + "!";

	// the number of blanks surrounding the greeting
	const int pad = 1;

	// the number of rows and columns to write
	const int rows = pad * 2 + 3;
	const string::size_type cols = greeting.size() + pad * 2 + 2;

	// write a blank line to separate the output from the input
	cout << endl;

	// write `rows' rows of output
	// invariant: we have written `r' rows so far
	for (int r = 0; r != rows; ++r) {

		string::size_type c = 0;

		// invariant: we have written `c' characters so far
		// in the current row
		while (c != cols) {

			// is it time to write the greeting?
			if (r == pad + 1 && c == pad + 1) {
				cout << greeting;
				c += greeting.size();
			} else {

				// are we on the border?
				if (r == 0 || r == rows - 1 ||
				    c == 0 || c == cols - 1)
					cout << "*";
				else
					cout << " ";
				++c;
			}
		}

		cout << endl;
	}

	return 0;
}
frame02.cpp

The program should be straightforward to follow -- it contains two loops to display the appropriate characters and greeting at the right time. You should be able to understand the logic behind the program. The textbook gives a detailed description of the evolution of the code and gives a good justification for many of the decisions adopted by the program. There are some new concepts being introduced in the above program:

Chapter 3: Working with batches of data

The sample programs in this chapter deal with reading a list of students grades (midterm, final, homework assignments) from standard input and calculating a final mark.

Using Average Assignment Mark (K&M § 3.1)

The first program below uses the average of the homework assignment marks in the calculation of the final grade. After obtaining the student's name, midterm and final exam marks, the program loops to input all the assignment marks and keeps a running total of these marks. Finally, it displays the overall final grade (using the average mark for all the assignments) for the student (with appropriate numeric precision).

#include <iomanip>
#include <iostream>
#include <ios>	
#include <string>

using std::cin;                  using std::setprecision;
using std::cout;                 using std::string;
using std::endl;                 using std::streamsize;

int main()
{
	// ask for and read the student's name
	cout << "Please enter your first name: ";
	string name;
	cin >> name;
	cout << "Hello, " << name << "!" << endl;

	// ask for and read the midterm and final grades
	cout << "Please enter your midterm and final exam grades: ";
	double midterm, final;
	cin >> midterm >> final;

	// ask for the homework grades
	cout << "Enter all your homework grades, "
	        "followed by end-of-file: ";

	// the number and sum of grades read so far
	int count = 0;
	double sum = 0;

	// a variable into which to read
	double x;

	// invariant:
	//     we have read `count' grades so far, and
	//     `sum' is the sum of the first `count' grades
	while (cin >> x) {
		++count;
		sum += x;
	}

	// write the result
	streamsize prec = cout.precision();
	cout << "Your final grade is " << setprecision(3)
	     << 0.2 * midterm + 0.4 * final + 0.4 * sum / count
	     << setprecision(prec) << endl;

	return 0;
}
avg.cpp

Some of the salient features of the above program are given below (they are all explained in greater detail in the text):

Using Median Assignment Mark (K&M § 3.2)

This program is similar to the one above except that instead of using the average mark of the homework to calculate the student's final overall mark, it uses the median (i.e. "middle") assignment mark. In order to determine the median, we must input and store all the assignment marks, sort them, then pick the one in the middle of the sorted list.

#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>
#include <vector>

using std::cin;             using std::sort;
using std::cout;            using std::streamsize;
using std::endl;            using std::string;
using std::setprecision;    using std::vector;

int main()
{
	// ask for and read the student's name
	cout << "Please enter your first name: ";
	string name;
	cin >> name;
	cout << "Hello, " << name << "!" << endl;

	// ask for and read the midterm and final grades
	cout << "Please enter your midterm and final exam grades: ";
	double midterm, final;
	cin >> midterm >> final;

	// ask for and read the homework grades
	cout << "Enter all your homework grades, "
	        "followed by end-of-file: ";

	vector<double> homework;
	double x;
	// invariant: `homework' contains all the homework grades read so far
	while (cin >> x)
		homework.push_back(x);

	// check that the student entered some homework grades
	typedef vector<double>::size_type vec_sz;
	vec_sz size = homework.size();
	if (size == 0) {
		cout << endl << "You must enter your grades.  "
		                "Please try again." << endl;	
		return 1;
	}

	// sort the grades
	sort(homework.begin(), homework.end());

	// compute the median homework grade
	vec_sz mid = size/2;
	double median;
	median = size % 2 == 0 ? (homework[mid] + homework[mid-1]) / 2
	                       : homework[mid];

	// compute and write the final grade
	streamsize prec = cout.precision();
	cout << "Your final grade is " << setprecision(3)
	     << 0.2 * midterm + 0.4 * final + 0.4 * median
	     << setprecision(prec) << endl;

	return 0;
}
med.cpp

Some of the important features of the above program are presented below (again, they are all explained in greater detail in the text):


Last modified: February 9, 2004 00:40:54 NST (Monday)