CMSC-341 Fall 2002

Project 1

Assigned 28 August 2002
Due 18 Sep 2002
Updates 3 Sep 2002
The order of the keys and values in the INSERT commands in the sample input was wrong. As per the project description the format of the command is INSERT <index> <key> <value>.
3 Sep 2002
Changed the description of the AList class in the project 1 page to say "construction of an AList as a copy of another AList" rather than "construction of an AList as a copy of another AListElement".


Background

Abstract Data Types (ADTs) are a central idea of this course and of object-oriented programming in general. Recall that an ADT has two parts: (1) a description of the elements that make up the type, and (2) a description of the operations allowed on instances of the type. The ADT idea is implemented in C++ as a class.

The ADT is one of the most powerful and important ideas in computer science. This project will give you some exercise in using ADTs.

Another important OOP idea, parametric polymorphism, is implemented in C++ by templates. This project will give you some practice with C++ templates.

You will be given a makefile, include headers from multiple directories, compile code from multiple directories, and use a set of class libraries. These are commonly used techniques in industry, so they're worth learning for future reference. You will be responsible for creating your own makefiles for all other projects.


Description

In this project you will implement a data structure called an association list, or alist. Alists are used to store unordered collections of values. Associated with each value in an alist is a unique key, and the key must be used to access the value. The term alist is borrowed from the Lisp language in which alists are implemented using lists as the underlying data structure. You will use vectors as the underlying data structure.

One way to understand an alist is to compare it with a simple array. Arrays are used to store values, and the values are accessed by specifying an integer that is the location of the desired value. The array index can be thought of as a key. In contrast, there is no notion of location with alists, and keys can be any class, not just integers. For example, you could associate the integer value 1 with the key "one", or in a different alist you could associate the string value "two" with the key 2. In the latter case, the fact that the key is 2 does not mean that the value "two" is stored at location 2. It just means that there's a value (i.e. the string "two") in the alist that was stored with the key 2 and that this key must be used to retrieve the value.

As part of this project you will use the vector template class in the Standard Template Library (STL) and the ANSI/ISO C++ standard library version of the string class. The STL is a collection of commonly used data structures and algorithms. You may freely use the vector and string classes in any project in this course. In general, no other classes from the STL can be used in any project.

The ADT that you will implement is described fully in the "ADT" section below. Use the description there to design your classes. Please remember that you must provide good documentation as described in the "Project Organization" handout.

Here are your tasks:

  1. Read the brief introduction to the STL at the following URL:

    http://www.msoe.edu/eecs/cese/resources/stl/index.htm

  2. Read and understand the description of the STL version of the vector ADT at the following URL:

    http://www.msoe.edu/eecs/cese/resources/stl/vector.htm

  3. Read and understand the description of the ANSI/ISO C++ standard library version of the string ADT at the following URL:

    http://www.msoe.edu/eecs/cese/resources/stl/string.htm

  4. Implement the AListElement class as a C++ template class. Instances of this class contain information about a single key/value pair stored in an AList.

  5. Implement the AList class as a C++ template class. Your class must use a vector of AListElements to store the current contents of the alist.
  6. Use the main function provided in the file:
  7. /afs/umbc.edu/users/o/a/oates/pub/CMSC341/Proj1/Proj1.C

    Use Proj1.C without making any changes to it. Note: There is no need to copy Proj1.C to your own directory. Your makefile must access the file from the directory in which it is provided. Do not submit Proj1.C.

  8. Write the set of auxiliary functions as required by Proj1.C -- getCmdLine( ), processIntStringCommands( ), etc. and put them in the file Proj1_aux.C. Their protoypes belong in Proj1_aux.H.

  9. Copy the makefile from

    /afs/umbc.edu/users/o/a/oates/pub/CMSC341/Proj1/Makefile

    to your own directory and modify it as needed. It can be used without modification if you follow the file names in the makefile.

  10. Answer the questions posed in 341-Fall02-proj1_questions.txt. Copy the file
  11. /afs/umbc.edu/users/o/a/oates/pub/CMSC341/Proj1/341-Fall02-p1_questions.txt

    to your own directory and edit it to provide your answers to the questions. Don't forget to submit the edited file; it's 10% of this project's grade.


Definition of the ADT

AListElement
An AList is a vector of AListElements. Each AListElement has a key, a value that is associated with the key, and an indicator of whether the element has been deleted. The type of the key and value must be template parameters for the class so that, for example, you can create an AListElement<int, string> that has an int key and a string value, or an AListElement<string, int> that has a string key and an int value.

The purpose of the deleted member requires a little explanation. We will use a technique known as lazy deletion when removing elements from an AList. That is, rather than actually removing the element, we will simply mark it as deleted. There are two reasons for using lazy deletion in this project. First, because vectors are used to store AListElements, without lazy deletion it would be necessary to copy all of the AListElements after the element to be removed down one position, which can be expensive. Second, to remove elements from a vector you need to understand iterators, which is something we cover later in the course.

With lazy deletion, removing a key/value pair from an AList simply requires finding the AListElement with the key and setting its deleted flag to true. It is important to consider the value of the deleted flag when searching for a value given its key (i.e. you want to be sure to skip elements that have been deleted) and when inserting new key/value pairs (i.e. you want to re-use deleted elements, remembering to set the deleted flag to false).

The operations allowed on an AListElement are:

AList:
An Alist is simply a vector of AList elements. The tricky thing about defining the AList is that the types of the keys and values must be template parameters, and these parameters must be used when declaring the vector of AListElements. That is, the template parameters used when declaring an AList must be used when declaring the corresponding vector of AListElements inside the AList class.

Note that a couple of the methods described below throw exceptions. You must write the exception classes, throw exceptions when appropriate, and catch exceptions that might be thrown to ensure that your program does not abort.

The operations allowed on an AList are:


The Command Line

Project 1 will be invoked with a command line that consists of two arguments. The first argument specifies the types of the keys and values and will be either "int-string", in which case the keys are ints and the values are strings, or "string-int", in which case the keys are strings and the values are ints. The second argument will be the name of a file that contains a set of operations that must be performed on ALists of the appropriate type. The format of this file is described in the command file section below.

Note that you must check command line arguments to ensure that they are valid, e.g. that the command file can be opened, and print an appropriate message if an error is found.


The Command File

Commands in the file specify operations to be performed on ALists. Each line in the file represents one command. Blank lines may appear anywhere in the file and should be ignored. Otherwise, you can assume that any line containing a command is syntactically well-formed. We make this assumption so you don't have to spend lots of time making the command file parser bullet proof.

Note that there are two routines for processing the command file depending on the types of the keys and values specified on the command line. These two routines should be very similar. It is probably a good idea to write, test, and debug one of them completely before starting on the other.

Also note that these two routines take an array of ALists. The main routine declares two arrays, one containing ALists with int keys and string values, and another containing string keys and int values. Depending on the command line arguments to the program, one of these arrays will be passed to a command processing routine. The commands described below all have as their first argument a number that is the index in this array of the AList on which the command is to be performed. You can assume that the array index is valid.

The command file format follows: