You are on page 1of 6

Duke APCS Workshop, A CourseDuke APCS Workshop, A Course

Day 1, June 20
We'll begin the workshop with a discussion of how classes should be used, what
C++ brings to educators and students in AP courses, and an overview of what's in
store for the workshop and for those who will be teaching AP courses this year
using C++.
We'll get quickly into C++ including much of the syntax of the language,
especially compared to Pascal. We'll discuss the apclasses apstring apvector,
and apmatrix and how these classes, and classes in general will be used in the
APCS A course.
As a starting point, we'll use the 1998 Exam in C++. (You should have received a
printout of this exam before the workshop, it's on the web too --- see the link
above which is to http://www.cs.duke.edu/~ola/ap/exams/cplus98.html).
We'll go over control structures like if, switch, for, and while. We'll discuss
functions, parameters (including value, reference, and const reference),
structs, classes, and streams for I/O. All these language features are used and
illustrated in the 1998 C++ Exam questions and solutions.
As part of the morning session we'll also use several classes that are not
official AP classes, but that we think are good tools to use in teaching the AP
course. These include
A class for representing calendar Dates, its header file is: date.h
A class for representing Dice (and random numbers), it's header file is:
dice.h
You can access all the classes we'll be using, both .h and .cpp files, in the
code directory. There's a zip file there too of all the classes (including the
apclasses) that's easier to download.
Day 1, Morning Session
We'll use the questions and answers from the 1998 Exam in C++, primes.cpp, which
finds prime numbers , usedate.cpp which shows the date class. and letters.cpp
which tracks the occurrences of each character in a file. We'll discuss the
apclasses and the syntax/semantics of C++.
In small groups of two or three you should think and write code to solve the
following problems. The idea is to discuss things in your group, but also ask
questions as they arise --- don't struggle too much with C++ details. For
problems labelled as "show-me", your group should write a solution to the
problem on a transparency. We'll show some of these solutions to the group as a
whole to see what kinds of different approaches were used.
Write a program that prompts the user for a string, and that prints the string
backwards.
Write a bool function IsPerfect that returns true if and only if it's single
integer parameter is a perfect number. Numbers like 6 and 28 that are equal to
the sum of their proper divisors: 6 = 1 + 2 + 3, 28 = 1 + 2 + 4 + 7 + 14, are
perfect numbers.
(show-me) Write a function Thanksgiving (header below) that prints the day of
month on which Thanksgiving occurs in the year specified by parameter year,
e.g., Thursday, November 26, 1998. Thanksgiving is the fourth Thursday in
November.
void Thanksgiving(int year)
// postcondition: prints date on which Thanksgiving occurs in year
{
}

Write a function like Thanksgiving, but which prints the day on which labor
day occurs. Labor day is the first monday in September.
Modify the program letters.cpp so that it prints the number of words of
different lengths, i.e., the number of 2-letter words, 3-letter words, etc.
that occur in a file, rather than tracking the occurrences of individual
characters.
show-me Sketch a design of a class that could be used in letters.cpp instead
of the existing code. Show the code in main and the public/private parts of
the class, but don't try to implement any member functions.

Day 1, Afternoon Session


After lunch, we'll meet first in D106, LSRC to go over the Codewarrior IDE and
to give a brief tour of both Visual C++ and Turbo C++. We won't go into great
detail, but we'll talk about projects, libraries, and issues in setting up an
environment for you and your students to program. After this discussion and
demonstration, we'll move to the lab for most of the afternoon.
Start the IDE/Compiler you'll be using, and get an AP project up and running.
You may not have time to work on all these programs, initially this is a chance
to get used to using projects and an environment as much as to C++.
Create a new .cpp file, called reverse.cpp (use the New option in the File
menu). Save this file, and add it to the project. Use your code from the
morning, prompt the user for a string, and print the string backwards. You'll
need to remember to use #include "apstring.h" to get access to the class
apstring. Get this program running; if you have time, modify the program to
check to see if the string entered is a palindrome before you move to the next
part of the lab.
Now remove reverse.cpp from the project, and create a new program (use new
from the file menu) called tgiving.cpp. Write a program that prompts the user
for a year, and prints the day on which Thanksgiving occurs in that year. Add
the file to the project, and compile, debug, and run the program. When it
works, modify the program to print the day on which Thanksiving occurs in all
years between two years the user enters, e.g., 1998 and 2008.
You'll now open letters.cpp and save it as another name so you can work on it
while leaving the original intact. You can find letters.cpp in the code folder
you copied onto the D: drive on your machine. After opening it, save it as
letters.cpp, but in your personal folder.
Then make letters.cpp the client program by opening it, adding it to the
project, and making sure that there is no other .cpp file with a main function
in the project (you may need to remove tgiving.cpp.) Run the program using
both poe.txt and hawthorne.txt as input files. These files are in the
subdirectory data, you'll need to type
y:\apcs\data\poe.txt

to access the data directory (it's possible that the data directory will move
after we've printed these notes, but unlikely).
Modify the program so that it tracks both lowercase and uppercase letters. For
the final output, you can print all the lowercase counts followed by the upper
case counts, or you can try to print two columns of output as shown below:

enter name of input file: y:\apcs\data\hawthorne.txt


a 28647 7.4% A 733 0.2%
b 5350 1.4% B 322 0.1%
c 9119 2.4% C 452 0.1%
d 15697 4.1% D 275 0.1%
e 49691 12.9% E 1162 0.3%
f 9212 2.4% F 105 0.0%
...

If you get this far, use the Save-As option in the File menu to rename the
program cletters.cpp. Add this to the project instead of letters.cpp. Then
turn this program into a classized version as you started to do in the morning
session.
Extra Stuff
Write a program to play a non-graphical, interactive version of the word-game
hangman. The user should guess a word "picked" by the computer. You can start by
storing a few words as constants in an apvector initialized when the program is
run, or read words from a file (or just use one word to get the program running,
then add more words).
You might try to design a class for the program, or use functions without
classes. Be sure that the program is robust: the user should not be penalized
for guessing the same letter more than once, all letters guessed should be
shown, and some representation of the word and the number of remaining guesses
should be shown as well.

Day 2, June 21
We'll begin by discussing a program for maintaining inventory in a cheese store.
The program can easily be modified to use CDs, books, cookies, or anything other
than cheese without difficulty.
The program is available in both Pascal and in C++ to provide easy points of
comparison between the languages. This is basically an array of structs with
some File I/O in Pascal and it's C++ equivalent.
cheese.pas
cheese.cpp
There are some design flaws in the C++ version that we'll discuss as part of the
workshop. In particular, you should be sure to note any questions you have about
C++ syntax, and about coding problems that may not necessarily be specific to
C++, but which are evident in the C++ version of the program (for example, what
can be done about the duplicated code when the user is prompted for the price of
the cheese and the amount in stock?)
Day 2, Morning Session
We'll use the cheese.cpp program to get at most of the features of C++ that
you'll need to cover in an A course.
There's no function in the class to change the amount of stock for a specific
cheese, i.e., to increase or decrease the amount.
show-me Write a member function for the CheeseList class that allows the user
to change the stock quantity for a specified cheese. You should decide on the
right interface for the function and then implement it. Consider: should the
user be prompted for a change amount in the function, or should the function
take a change amount as a parameter?
(Sketch) Modify the program so that the user has the option of changing the
stock (call the member function you wrote in the previous problem when the
user chooses the proper item from the menu.)
Assume the private member function sort is written, where should it be called?
How can the user be given the option of sorting alphabetically or by price?
Day 2, Morning Lab: Baseball Vendors
After discussing the code and class design for the cheese.cpp program we'll head
to the lab where you'll work on a similar program in which the data and
operations are similar, but the changes you'll need to make will help you get
used to C++ and the programming environment.
Assume that data for the vendors at a baseball stadium are stored in a file as
follows:
5
Frank Jones
peanuts
100.50 90.00 80.00 110.50 75.00
Myrna Smeltz
beer
250.00 210.00 350.00 00.00 200.00

The first line of the file is the number of games played, this is the number of
items on the third line for each vendor. In general, there are three lines of
data for each vendor: the name (first and last, separated by a space on the
first line), the item sold by the vendor on the next line, and the sales per
game, all on the third line, each game-sales separated from others by
whitespace.
Write a program (using a class or not) that reads the data in from a file, and
offers the user several options:
Print a list of all vendors, total sales, and average (per-game sale).
Add a new vendor for the list (assuming no sales in any games played so far).
Add a new sales figure for all vendors, e.g., after a new game is played.
Print a list of just the peanut vendors (or just the beer vendors, or just the
some-product-entered-by-user vendor).
Print a list of vendors sorted by total sales.
Don't try to write the entire program at once, you have to get the data into the
program and print it before going to some other part of the program. You should
think about all pieces in the design phase, but implement one member function at
a time.
Here are some hints on the input. There are two (at least) ways of viewing the
input: line-oriented, or free-flowing. If you view it as free-flowing, and make
some reasonable assumptions, the I/O is easier than if you try to do
line-oriented input.
free-flowing format Assume each vendor has a first and last name (no other
spaces for names than between these two). Assume all items being sold are
single words, no spaces. Then you can do the input using only the extraction
operator >>, e.g., read first, last, for-sale-item, then all the values of the
quantities sold (the same for all vendors).
line-oriented You'll need to use getline for input rather than extraction >>.
This means you MUST read strings. You can parse the strings, by looking for
spaces using the apstring member function find, or you can use input string
streams, although in Codewarrior 3.0 these are complicated (don't use them
during the workshop, the instructors haven't figured out the ramifications of
using the new C++ class istringstream rather than the more common, but older,
class istrstream.)
To read the numbers, you can use extraction >>, but you'll need to read the
end-of-line character(s) by using a getline to process the unread end-of-line
characters, e.g., you could do something like the code below (don't use this
code, it's pseudocode and doesn't reflect the use of a class).
int k,gameCount;
apvector<double> soldAmount(30);
apstring dummy;

for (k=0; k < gameCount; k++)


{
input >> soldAmount[k];
}
getline(input,dummy); // read past end-of-line chars

Use this program as a starting point, if you need help on a section ask, and we
can provide hints or code to get you going.

Day 2, Afternoon Session


In the afternoon, we'll discuss the C++ version of the case study which uses a
class BigInt. You can see the entire case study online at the college-board
website. The code has been copied locally as bigint.h and bigint.cpp.
We'll discuss parts of the BigInt class at a relatively high level. As we'll
discuss, we do NOT recommend going over how every constructor works behind the
scenes in evaluating expressions like those below.

BigInt a,b;

a = 13;
b = 10 * c + 1;

Part of the attractions of using the BigInt class is the abstaction of not
worrying exactly how ints are converted to BigInts, for example. You should try
to understand this yourself, and we'll discuss it during the workshop, but A
students do not need to understand precisely how many temporary variables are
created in evaluating the last mixed BigInt and int expression above: b = 10 * c
+ 1.
show-me Write a member function Zeroize to change the last n digits of a
BigInt to zero, where n is the only parameter to Zeroize.
Then write a non-member function that does the same thing. See the header
below. You may want to use the member function ToString.
void MakeZero(BigInt & big, int n)
// precondition: 0 < n <= big.NumDigits()
// postcondition: rightmost (least significant) n digits of
// big are equal to 0.

What changes must be made to the BigInt class if instead of storing the number
1,234 in the order [4,3,2,1] (where 4 is in the 0th, or first, cell in the
apvector myDigits), the characters are stored in the order [1,2,3,4]? How do
you think this will affect the running times of the arithmetic operators as
they're coded?

Day 2, Afternoon Lab


There are more activities in this lab than you'll be able to finish. We'll stop
in time to debrief about the entire workshop. You're free (of course) to work on
other programs.
Using the SysTimer class declared in systimer.h (already included in the
library you're using) determine, empirically, the time needed to square an
N-digit BigInt, where N varies from 0 to 900 in increments of 100. Make the
N-digit number all 9's for a good upper bound. You can construct such a BigInt
from a string formed by concatenating 9's together. Output might be similar to
the following (from a Penium 133 running Turbo 4.5). You can determine the
number of digits in a BigInt by using the ToString member function (then using
length).
#dig ^2 dig time
0 1 0
100 200 0.11
200 400 0.5
300 600 1.16
400 800 2.09
500 1000 3.3
600 1200 4.84
700 1400 6.48
800 1600 8.46
900 1800 10.66

The hailstone sequence is formed by using the following iterative technique


for a number n:

int f(int n)
{
if (n % 2 == 0) return n/2;
else return 3*n + 1;
}

while (n != 1)
{
n = f(n);
}

It is conjectured, though unproven, that this loop always terminates. Write a


program to find the BigInt value N that yields the longest hailstone sequence.
Limit the search between two user-entered values.

Owen L. Astrachan
Last modified: Fri Jun 19 12:37:36 EDT 1998