Spring 2006 - Programming Project 6
40 points
Out: March 24, 2006
Due: April 7, 2006 (Friday)
Consider a filing cabinet. Each cabinet consists of one or
more drawers that contain zero or more folders in each drawer. We
will assume that the folders contain information that can be arranged
in some ascending order by an integer key value (e.g., ID number) and
that they are stored in the cabinet in that order. To make folders
easier to find, the maximum key value that may be contained in a
drawer is marked on the front of the drawer and the drawers are
ordered by their maximum key values. This implies that a folder is
stored in the drawer with the smallest maximum key value larger than
the folder key.
We can model such a filing cabinet as a (singly) linked list
of drawers with each drawer containing a (singly) linked list of
folders. The diagram below illustrates the structure (only) of the
filing cabinet.
The specifications for this project are as follows. There are three template structs and classes where the template parameter is the type of the information being kept in the folders: a folder list node (FolderNode<T>), a drawer list node (DrawerNode<T>), and the filing cabinet object itself (FilingCabinet<T>). For this project, we specify the maximum number of folders that will fit into a drawer, but we can add another drawer to a filing cabinet anywhere and at anytime.
The FolderNode struct template is used to form a linked list of folders in a drawer. The user is required to provide an integer, called a key for each information object that is suitable for ordering the folders within the cabinet.
| Object | Type | Name |
| key value | int | key |
| information to store | T | item |
| link to next folder | FolderNode<T>* | next |
| Objects | Default | Type | Kind | Movement | Name |
| key value | 0 | int | variable | received | aKey |
| information | T() | T | variable | received | anItem |
| link to next folder | null | FolderNode<T>* | variable | received | aLink |
The DrawerNode struct template is used to form a linked list of drawers in a filing cabinet.
| Object | Type | Name |
| maximum key value | int | maximumKey |
| number of folders in the drawer | int | numFolders |
| link to folder list | FolderNode<T>* | folderList |
| link to next drawer | DrawerNode<T>* | next |
| Objects | Default | Type | Kind | Movement | Name |
| maximum key in the drawer | INT_MAX | int | variable | received | maxKey |
| link to next drawer | null | DrawerNode<T>* | variable | received | aLink |
The FilingCabinet class template ties everything together.
| Object | Type | Name |
| link to first drawer | DrawerNode<T>* | drawerList |
| maximum number of folders per drawer | int | maxFolders |
| total number of folders in cabinet | int | totalFolders |
Explicit-value constructor - creates a filing cabinet from a
vector of items whose keys are in a corresponding vector of integers,
and also initializes the maximum number of folders per drawer and the
maximum key value to the given arguments (or defaults). Each item is
put into a folder (node) that is then put in a drawer (node).
| Objects | Default | Type | Kind | Movement | Name |
| list of items | --- | vector<T> | variable | received | initItems |
| list of corresponding keys | --- | vector<int> | variable | received | initKeys |
| maximum number of folders | 25 | int | variable | received | initMaxFolders |
| maximum key value | INT_MAX | int | variable | received | initMaxKey |
Copy constructor - creates a new FilingCabinet object that is
a copy of an existing FilingCabinet object.
| Objects | Type | Kind | Movement | Name |
| original FilingCabinet object | FilingCabinet<T> | variable | received | original |
Destructor - deallocates the folder and drawer nodes.
operator= - overloaded assignment operator function.
Copies original FilingCabinet object into an existing FilingCabinet object.
| Objects | Type | Kind | Movement | Name |
| original FilingCabinet object | FilingCabinet<T> | variable | received | original |
| this FilingCabinet object | FilingCabinet<T>& | variable | returned | *this |
AddFolder - inserts the given item with the given key in order
into the drawer with the smallest maximum key value larger than the
given key, and increments the number of folders in the drawer it is
placed in and the total number of folders. If the given key is
already in the cabinet, throw a DuplicateError with an appropriate
message (see below regarding exception objects). If the given key is
larger than largest maximum key value, then throw a RangeError.
If the drawer is full (i.e., it holds the maximum number of
folders), insert a new drawer and put half of the folder list of the
original drawer into it, appropriately setting the number of folders
and the maximum key value, then proceed to add the new item to the
appropriate drawer.
| Objects | Type | Kind | Movement | Name |
| item to be added | T | variable | received | item |
| key for item | int | variable | received | key |
RemoveFolder - removes the item with the given key, decrements
total number of folders and the number of folders in the drawer it is
removed from. If the key is not in the cabinet, throw a NotFoundError
with an appropriate message (see below regarding exception objects).
Note that this may result in an empty drawer, which is allowable.
| Objects | Type | Kind | Movement | Name |
| key for item | int | variable | received | key |
GetFolder - returns the item (not the node) with the given
key. Returns a reference to allow item to be manipulated directly.
This version is non-constant. If the key is not in the cabinet, throw
a NotFoundError with an appropriate message (see below regarding
exception objects).
| Objects | Type | Kind | Movement | Name |
| key for item | int | variable | received | key |
| item with key | T& | variable | returned | --- |
GetFolder - constant version with the same analysis as the
non-constant version above. If the key is not in the cabinet, throw a
NotFoundError with an appropriate message (see below regarding
exception objects).
GetTotalFolders - returns total number of folders in the
cabinet.
| Objects | Type | Kind | Movement | Name |
| total number of folders | int | variable | returned | totalFolders |
ListFolders - output the item in each folder from each drawer
using operator« separated by the given separator string (or
default). The drawers should be numbered consecutively starting with
1 and the number of folders and maximum key in each drawer should be
output as well. The output for the above diagram might look like:
Drawer 1: 3 folder(s), max key is 250 <item information for 123> <item information for 178> <item information for 250> Drawer 2: 0 folder(s), max key is 428 Drawer 3: 1 folder(s), max key is 637 <item information for 543> Drawer 4: ... : : Drawer n: 5 folder(s), max key is 999 <item information for 834> : : <item information for 987>
| Objects | Default | Type | Kind | Movement | Name |
| output stream | --- | ostream& | variable | received & passed back | out |
| separator | "\n" |
string | variable | received | separator |
FindDrawer - a private helper member function that
returns a pointer to the drawer that might contain the folder with the
given key. Returns null if the key is larger than the largest maximum
key value. Must be used by AddFolder, RemoveFolder, and
GetFolder.
| Objects | Type | Kind | Movement | Name |
| key for item | int | variable | received | key |
| drawer that may contain item | DrawerNode<T>* | variable | returned | --- |
Put the implementations for all three structs and classes into
one file cabinet.h in the order presented above.
(This is because you cannot really use the node structs independent of
the filing cabinet class so you might as well put them in the same
file.) For the struct templates, the constructor
implementation should be written in-line in the struct definition as
shown in class. The FilingCabinet operation implementations should
be separate template function definitions. If you wish to write
template functions for list operations such as CopyFolderList or
DeleteFolderList, put them in this file as well. (Use comment blocks
to identify the different sections of the file.)
A driver program (cabinetdriver.cpp), a sample data
file (students.dat), and a new except.h that
defines the DuplicateError and NotFoundError exception objects will
be made available by Wednesday, March 28, in directory
/home/hwang/cs215/project6 on csserver. This program will
define a StudentInfo struct containing a name and student ID and
create several filing cabinets of these structs. The student ID will
be used as the folder key.
You must submit a makefile for this project that compiles the
driver program even though there will be only one object file target
(cabinetdriver.o). Submissions without working makefiles
will be assessed up to 3-point penalty as indicated in the syllabus.
Follow the guidelines in the C++ Programming
Style Guideline for CS 215 handout. As stated in the syllabus, part
of the grade on a programming project depends on how well you adhere
to the guidelines. The grader will look at your code listing and
grade it according to the guidelines.
Submit a tar file with your makefile and cabinet.h.
Turn in a hardcopy of your makefile and cabinet.h. Please
do not submit the driver program, the sample input file,
object files, or executable files (either in the tarfile or in
hardcopy).
REMINDER: Your project must compile for it to be
graded. Submissions that do not compile will be returned for
resubmission and assessed a late penalty.