This assignment contains two parts. The first part is numbered assignment 3, which is due at 9 P.M. on Wednesday, February 11th, 2004. The second part is numbered assignment 4, which is due at 9 P.M. on Wednesday, February 18th, 2004. Exception: the README file for homework 4 is due at midnight on the 18th (i.e., the moment Thursday begins).
This assignment will give you more practice writing basic C++ code, manipulating pointers, and allocating/freeing memory.
It is a little-known fact that Harvey Mudd has a sister school, Deep Glen Polytechnic, in northern Scotland. Because the depressed state of the Scottish economy has limited their funding, their registrar currently maintains course rosters by hand, using 3x5 cards. Your job is to provide them with a rudimentary course database system.
As well as being the finest scientific college in Europe, Deep Glen Polytechnic is famous for its playful students. A longstanding tradition at Deep Glen is that students attempt to confuse professors by changing their appearance frequently, notably by dying their hair, so that the professors will have trouble remembering the names of individual students even though there are only 128 of them in the entire school. The professors have countered this game with a nasty trick of their own: they keep changing the meeting times of their courses, so that almost nobody will be able to show up at the correct time and therefore there will be fewer names to learn.
The registrar, fondly known to all as Jeanne "Lumpy" MacBettykin, has been caught in the middle of this battle. The professors have required her to keep track of the current hair color of all students, while the students have successfully bribed her (using precious chocolate-chip cookies sent to them by their doting mothers) to also track time changes and periodically provide them with printouts showing the latest times. Your new database program must therefore support these features.
This is actually the second attempt to automate DGP's course registration system. An earlier, buggy version was written by a physics student at DGP, now long since gone. Because the registrar is now accustomed to the earlier user interface, you must rebuild the deeper levels of the code but keep the user interface intact.
Specifically, you are provided with the following files:
As usual,
you must get these files by using "cs70checkout
hw03
".
These files contain a working implementation of the interactive user
interface.
Your job is
to implement the registrar database, Registrar_DB
, and
its supporting
classes, Course
and Student
.
A critical part of this assignment is that you must match the style of the existing code. Any code you add must conform to the style of the code you have been given.
The class Registrar_DB
holds the following data:
The lists of courses and students are kept in the order in which they were inserted. Do not attempt to sort or alphabetize them.
The class Student
holds the following data:
Course
s (at most 5) currently
being taken,
The array of pointers to courses is not sorted; instead, it is kept in
the order in which courses were added. When a student drops a course,
the associated pointer should be set to NULL
(zero), and
the array should not be compacted or otherwise reorganized.
When a course is added, the first NULL
Course
pointer should be used to add a pointer to that
Course
.
The class Course
holds the following information:
Student
s in the course),
The roster for each course is kept alphabetized by name. Alphabetize using the whole fullname string. Don't attempt to separate the first and last name.
The interactive interface supports the following commands:
The two display commands should show the full information associated with each course or student, and should be identical to the sample outputs (see below).
Each course contains an array of pointers to students in the course. The data in this array should be kept packed: if you remove a student that isn't the last one in the array, you must move the subsequent items in the array to close up the gap.
Each student contains an array of pointers to courses being taken.
The data in this array should not be kept packed: if you remove a
course that isn't the last one in the array, you should simply set the
pointer to NULL
. A later "add" can then re-use this pointer.
Note that this requirement is different from the requirement
for the Course
class.
The Registrar_DB
class contains an array of all students.
The Course
class contains an array of pointers to
students. Notice that these two arrays are of different type. We did
this deliberately so that you could practice manipulating both types
of arrays. The same applies to the arrays of courses in the
Registrar_DB
and Student
classes.
The top-level interactive interface assumes that there are no more than 128 students and no more than 20 courses. These limits are fixed by the trustees of DGP. Therefore the program should generate an error if these limits are exceeded rather than dynamically expanding these arrays.
Students and courses can be added to the arrays in
Registrar_DB
but they are never deleted. Nevertheless,
you must provide proper destructors.
If you quit using a piece of memory, be sure to deallocate it.
To encourage you to start early, and to encourage you to design well, we are requiring you to submit pseudocode for this assignment. If you don't know what "pseudocode" means, it refers to writing in a mix of English and C++ (or some other language), such that it is reasonably easy for another programmer to convert to write actual working code.
Pseudocode is never given to a compiler; it is intended only for humans. That means you don't have to worry about nasty details of syntax, and you don't have to take care of every last little thing. Here is a simple example of pseudocode:
grades = Allocate 100-element array of doubles set each element of grades to zero limit = minimum(number of students, size of grades) for j = 0 to limit // copy grades to "grades", or set to zero if no submission if student[j] submitted homework 1 grades[j] = student j's homework #1 grade else grades[j] = 0.0 // ... free memory allocated for grades
Note several things about the above example:
For assignment 3, you must create pseudocode in the following files:
At the same time, you must also avoid submitting pseudocode that is so high-level that it does not clearly state the approach. Ideally, good pseudocode can be translated into working code by a reasonably good programmer. If you aren't sure about the level of your code, talk to the professor or a tutor before you get very far into the project.
Some functions in the skeleton program are so simple that it is silly to pseudocode them. Those functions contain the comment "ADD STUFF (PSEUDOCODE NOT NEEDED)". You will have to complete those functions for assignment 4, but it is not necessary to write pseudocode for them for assignment 3.
Use cs70submit
to submit your solution, as usual.
For assignment 4, you must submit a final working program. All of your pseudocode must be converted to real code, tested, and debugged.
Before you begin working on assignment 4, you must create an empty
directory to work in by using cs70checkout
, and
then copy all your hw03 files into the hw04 directory and tell
the submission system about them. The commands you'll need are:
cs70checkout hw04 cp hw03/* hw04 cd hw04 cs70submit *
For assignment 4, you must submit the following files:
Your code must compile and run with the supplied copies of registrar.hh and assign_03.cc.
A SPECIAL WARNING: the sample README files provided on the homework policies Web page are from a previous term's version of this assignment. Take great care to avoid unintentional plagiarism. We suggest that if you have not previously looked at these files, you first write your README without reference to them, and then browse them to see how your own README stacks up.
To help you with this assignment, Prof. Fleck has written some useful Web pages on doing I/O in C++.
For this assignment, you are allowed (expected) to use the C++ string
type. This type is defined in the include file <string> (note
that there is no .h
suffix), which has already been
included for you in the various header and source files.
Strings are a first-class C++ type, so you can read, write, create,
delete, copy, and assign them just as if they were integers. In
addition, the +
operator concatenates strings, which you
will find very convenient for this assignment.
When you run the program, you will find that there is a simple interactive interface that will prompt you for commands and let you test various operations. To help you see how your program should behave interactively, we have provided a log of a sample interactive session with the program.
When you begin to be confident that your code works, you can run two tests against our sample output files, both of which were generated from the same input file.
allout.txt
cout
(where listings are
printed) and cerr
(where prompts and errors
are printed). This file contains everything that the
program would write to the terminal if you ran it
interactively.
noerrs.txt
cout
. This file
contains the listings of courses and students that are
produced by the "show courses" and "show students"
commands.
The above files will be included when you first check the assignment out.
You can compare your output to the samples with the following commands. Note that they are different for tcsh and bash users.
For tcsh users, do:
% ./assign_03 < input.txt |& diff - allout.txt % (./assign_03 < input.txt | diff - noerrs.txt > temp) >& /dev/null % cat temp % rm temp
Bash users can do:
% ./assign_03 2>&1 | diff - allout.txt % ./assign_03 2> /dev/null | diff - noerrs.txt
If everything is working correctly, none of the commands should produce any output.
If diff
reports differences, but you can't spot them, the
differences may be in the whitespace. Try passing the output of
diff
through cat -vet
:
% ./assign_03 < input.txt |& diff - allout.txt | cat -vet % (./assign_03 < input.txt | diff - noerrs.txt > temp) >& /dev/null % cat -vet temp % rm tempor for Bash:
% ./assign_03 2>&1 | diff - allout.txt | cat -vet % ./assign_03 2> /dev/null | diff - noerrs.txt | cat -vet
Depending on the editor you use, you may find it difficult to get your editor to conform to the style requirement for this assignment. Here are some hints:
The easiest way to get emacs to cooperate is to tell it to stop trying
to outsmart you. If you execute M-x fundamental-mode RET
,
you will place the editor into a
mode where it will simply do what you type, instead of "helping" by
forcing a particular formatting style on you.
The price you will pay is that you will lose the highlighting of
keywords and all of the magic "electric" features. There are fancier
approaches that will retain some of those things, but they are beyond
the scope of this document.
If you want to always do this for C/C++ files, add the following lines
to your .emacs
file:
(setq c-mode-hook '(fix-c-mode)) (setq c++-mode-hook '(fix-c-mode)) (defun fix-c-mode nil "Fix up C mode so that it is usable by my standards" (fundamental-mode) )
Execute the following commands in colon mode, or add them to your
.vimrc
file:
set cino=>4{4(4 sw=4 " Kuenning-style indentation set comments=sr:/*,mb:*,el:*/ " C-style comment formatting " Enable these formatting options for .cc and .hh files: au BufEnter *.cc,*.hh set cindent tw=78 fo=tcqro(Thanks to Matt Brubeck for providing these configuration lines.)
As usual there are some tricky parts to this assignment. Some of them are:
assign_03.cc
. Even though you do not have to
change it, you should understand how it uses the code you
do
have to write. In essence, the code in
assign_03.cc
is a specification for your own
code.
assign_03.cc
will not try to add a student
to a full course, your own code should double-check to make
sure there is room in the course. That way, if somebody later
breaks assign_03.cc
, the program won't crash
horribly (this technique is called "defensive programming").
ostream
. The value returned should simply be the
stream that was passed as an argument.
© 2004, Geoff Kuenning
This page is maintained by Geoff Kuenning.