CS 70, Spring 2004
Assignment 3: Registrar Database

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.

Motivation

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.

What you need to build

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 classes

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:

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:

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).

Technical details

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.

Assignment 3

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:

  1. Some of the code is almost C++; other stuff is very far from C++. (e.g. "set each element of grades to zero").
  2. The syntax is inconsistent, but the meaning of each statement is clear.
  3. There are no curly braces; grouping is indicated with indentation.
  4. Every important detail of the algorithm is included in the code.
  5. The code assumes that the reader can figure out standard constructs (like a loop to initialize an array).
  6. Comments are still important, but since the English is somewhat more self-explanatory, fewer comments are needed.
  7. There is a potential bug in the above pseudocode, depending on how the English is interpreted. (Can you find it?)

Submission mechanics for assignment 3

For assignment 3, you must create pseudocode in the following files:

For each of the above 6 files, you should replace any "ADD PSEUDOCODE" comment with whatever pseudocode is necessary. (There will be a few places where "necessary" equals "nothing", but in most places you'll need to write at least a few lines.) DO NOT submit perfect C++ code. If you submit C++ code, or something that is even close to compiling, you will receive a much lower grade, even if the code works correctly. The point of this assignment is to teach you to use pseudocode as a design tool, and if you submit a working program we will have no way of knowing whether you used pseudocode. Good pseudocode skips over the messy but obvious details, and concentrates on developing the tricky parts of the algorithms. (However, if a detail is tricky, it can be good to mention it in the pseudocode so you won't forget it later.)

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.

Assignment 4

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 *

Submission mechanics

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.

Useful information

To help you with this assignment, Prof. Fleck has written some useful Web pages on doing I/O in C++.

C++ strings

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.

Testing

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
is the contents of both 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
is the contents of only 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 temp
or for Bash:
    % ./assign_03 2>&1 | diff - allout.txt | cat -vet
    % ./assign_03 2> /dev/null | diff - noerrs.txt | cat -vet

Getting your Editor to Cooperate

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:

For Emacs

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)
  )

For Vim

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.)

Tricky Stuff

As usual there are some tricky parts to this assignment. Some of them are:


© 2004, Geoff Kuenning

This page is maintained by Geoff Kuenning.