C M S C     2 1 4
C o m p u t e r   S c i e n c e   I I
S p r i n g   2 0 0 2


Project #1

Due Wednesday, Feb 27th, by 11pm (NEW!)
Due Tuesday, Feb 26th, by 11pm

Last updated: February 21, 2002

Previously updated: February 18, 2002

Previously updated: February 12, 2002

Read the FAQ for updates/corrections. Items that have changed from the previous version will be marked in red to make it easier to spot changes.

Purpose

  1. To learn when and when not to implement: copy constructor, assignment operator, and destructor.
  2. To understand what an abstract data type is, in particular, a Sorted List.
  3. To develop container classes: MovieArrayList and MovieSortedList using dynamic arrays and sorted doubly linked lists, respectively.
  4. To write test drivers to test the classes you implement.
  5. To learn how to write preconditions, postconditions, class invariants.
  6. To learn how to plan/design classes.
  7. To write classes with good programming and commenting style.
  8. To write documentation for classes.

Academic Integrity Statement

Please note that *all* programming projects in this course (including this one) are to be done independently or with the assistance of the instructional staff of this course only.

Please review the policies outlined on the class syllabus concerning the use of class computer accounts and concerning the University's Code of Academic Integrity. The instructors of this course will review the programs submitted by students for potential violations of the Code of Academic Integrity and if it is believed that a violation has occurred it will be referred to the Office of Judicial Programs and the Student Honor Council.

Hardcoding is considered a violation of academic integrity

Checklist

Click here before submitting.

Project 1 Checklist

Background

This is a more substantive project than Project 0, so you are expected to start working right away if you expect to be complete the project.

Furthermore, you will be given a description which will be implemented as Project 4. You must write a description of all classes that you think you will need to solve that project. In addition to the the coding part of the project, you will spend the next 3 projects planning out classes, etc., needed for the fourth project.

Background Reading

Please read the following as you do the project.

Files Provided

In addition to the primary input and primary output, the following files are in the posting account under Projects/P1.

Files Submitted

You should submit all the files provided.

Furthermore, you will need to submit the following files.

(CHANGE) You do not have to submit the test drivers (i.e., MovieDriver, MovieSortedListDriver, MovieArrayListDriver) as separate files. Instead, read the section at the end on "Test Drivers, Revisited" to see how you should submit your driver. (It will be part of the file you submit for each class you are testing).

Tasks

The following is a suggested way to approach the project.

Task 1: Implement Movie.cpp given Movie.h

You will need to implement the following operations:

In addition, there are three non-methods (i.e., non member functions).

compare() function

This will be a plain C++ function, NOT a member function. It takes two parameters. It will behave like strcmp in the following way:

To be more specific, this is how we compare movies. Each movie stores a list of words that represents a movie's title. For example, "Gone", "With", "The", "Wind" would be stored as the first four elements of a Movie object. Each element stores one word.

Here's the pseudocode for compare:

  1. Initialize i to zero.
  2. Compare the word i of two movies. If the words are different, then determine (using the built-in string comparison functions for C++ style strings) whether word i of the first movie is smaller than word i of the second movie, or they are the same, or word i is greater than word i the second.

    For example, if you are comparing { "Gone, "With", "The", "Wind" } (which is the first movie) to { "Matrix" }, then because "Gone" < "Matrix", then the first movie is smaller than the second, and the function would return -1.

  3. If word i is the same, increment i by 1 (i.e., compare the next word of both movies).

    However, if at least one of the movies doesn't have word i, then do the following:

    • If both the first and second movie have the same number of words (say, n), and i is n, then the two movies must be the same (e.g., if i = 4 and both the first and second movies are { "Gone", "With", "The", "Wind" }).
    • If the first movie has fewer words than the second (thus, there is no word i for the first movie, then the first movie is less than the second (e.g., the first movie is { "Alien" } and the second is { "Alien", "Resurrection" }), then return -1 since the first movie is smaller than the second.
    • (CORRECTION) If the first movie has more words than the second (thus, there is no word i for the second movie, then the first movie is greater than the second (e.g., the SECOND movie is { "Alien" } and the FIRST is { "Alien", "Resurrection" }), then return 1 since the first movie is greater than the second. and quit, otherwise if both movies have word i go to step 2.

The algorithm isn't quite complete. Here are two complications that you must also handle.

  1. The comparison is case-insensitive. Recall that comparison operators for C++ style strings are case-sensitive. The primary inputs will not test this. The secondaries may test them.
  2. If the first word of a movie's title is "A", "An", "The", then it should be ignored for comparison purposes. For example, { "An", "Affair", "To", "Remember" } and { "Affair", "To", "Remember" } would be considered the same film, as would { "An", "Affair", "To", "Remember" } and { "The", "Affair", "To", "Remember" }. The primary won't test this either, but the secondaries will.

Copy Constructor, Assignment Operator, Destructor

If this class REQUIRES these three methods, implement them (and also implement init(), copy, and freeMem()). See the background reading on writing these three methods. If, on the other hand, the implicit versions of the copy constructor, assignment operator, and destructor work (i.e., the class behaves correctly), DO NOT implement these methods, nor their helpers.

Testing Movie

(UPDATED)

As you write the code, you should write a static method for Movie called runTestDriver() (see "Test Driver, Revisited" below). These tests should print out messages to the screen, checking for assignment operator, copy constructor, and all the methods shown. Initially try to get the print functions to work, so you can test the other ones. Go to the Tutorial section, and read up on writing test drivers.

Write Movie.doc

Do this as you are coding up this class.

Task 2: Implement MovieSortedList

This is a doubly linked list. You have similar tasks to MovieArrayList, but they are more complicated. Unlike the MovieArrayList which is unsorted, this list is sorted in increasing order, based on the comparison operators of Movie (which themselves rely on compare()).

Note that the iterator will be implemented differently in MovieSortedList than in MovieArrayList. This points out the differences between iterating an array and a linked list.

Node should already be in the class, so you just need to implement the methods.

Some restrictions:

This is a description of what each method does:

In addition, you must decide whether to implement the copy constructor, assignment operator, and destructor. If the implicit versions are fine, then do NOT implement these methods. However, if the implicit methods are NOT sufficient, you must implement these methods, and also implement init(), copy(), freeMem(). See reading about singly linked lists to see how these helper methods should be used.

Methods Used in Node

A list of methods used in Node.

Methods Used in ConstIterator

A list of methods used in the ConstIterator nested class.

Think about why it's not necessary to write a copy constructor, assignment operator, and destructor for this nested class.

Testing MovieSortedList

(UPDATED)

As you write the code, you should write a static method for MovieSortedList called runTestDriver() (see "Test Drivers, Revisited" below). These tests should print out messages to the screen, checking for assignment operator, copy constructor, and all the methods shown. Initially try to get the print functions to work, so you can test the other ones. Go to the Tutorial section, and read up on writing test drivers.

Write MovieSortedList.doc

Do this as you are coding up this class.

Task 3: Implement MovieArrayList

Note: if you are pressed for time, you may wish to start working on MovieTester and MovieSortedListTester before working on this class. While we will test this class, it will not appear in the primary.

Note that the iterator will be implemented differently in MovieSortedList than in MovieArrayList. This points out the differences between iterating an array and a linked list.

Some restrictions:

This is a description of what each method does:

Determine whether it is NECESSARY to write the copy constructor, assignment operator, and destructor. If so, write them. If it's unnecessary, meaning the implicit versions are correct, then don't implement. Note: when copying this object, a deep copy should be made.

Methods in ConstIterator

All of these methods are similar to the ones in MovieSortedList. The difference? Since you have an array element, you will use pointer arithmetic to move curr.

Also, the relational operators will compare the pointers using relational operators (note: pointers can be compared). Don't worry if two iterators are pointing to elements in different lists. This would be hard to check for. Merely compare curr of one iterator to another.

Finally, the only unusual constructor is the constructor which takes an Iterator object. This allows an iterator to be saved to a const iterator.

The following are a list of all methods:

Methods in Iterator

Again, similar to those in ConstIterator.

The only unusual method is: makeConstIterator. This method creates a ConstIterator with its curr matching the curr of the current iterator.

The following are a list of all methods in this nested class:

Testing MovieArrayList

(UPDATED)

As you write the code, you should write a static method for MovieArrayList called runTestDriver() (see "Test Driver, Revisited" below). These tests should print out messages to the screen, checking for assignment operator, copy constructor, and all the methods shown. Initially try to get the print functions to work, so you can test the other ones.

Write MovieArrayList.doc

Do this as you are coding up this class.

Task 4: Finish MovieTester

This is used to test the primary input. The only operaions that are missing are handling the other relational operators. It should be straightforward to implement them.

Almost all of this class has been written. However, if any bugs remain, you will need to debug it. No bugs have been deliberately left in, however.

A description of the tester files appears in later sections below.

Task 5: Write MovieSortedListTester and MovieArrayListTester

These classes should work with main() and handle a few simple operations such as declaring an object, copying an object, printing the size, determining if the list has the correct items in it, in the correct order, declaring an iterator, moving it around and printing it. Write the MovieSortedListTester first since that's the only required by the primary input. The MovieArrayListTester will be checked only in secondary inputs, and is not required for a successful submission.

See section about testers below.

Task 6: Finish main.cpp and test, test, test!

Yeah, what the task said...

There's not much to add to it, so you should be able to use the file as is (uncommenting sections as needed).

Assumptions/Restrictions/Requirements

Project 4 Background

In the following link, you will read a description of what will be required in project 4. At this point, the description is sketchy. Your goal is to determine what classes you think will be necessary for this class, and hopefully, some methods that you may need. By that point, you will use some version of the MovieSortedList and MovieArrayList (which will then store other things besides movies.

In a plain text file called Proposal.doc, describe the names of the classes you think you will need. Explain what each class will do. If you think you can write the data members and methods, you can do that, too.

Here is the Project 4 Preview

Tester Classes

You will have to write/complete the implementation/debug three tester classes: MovieTester, MovieSortedListTester, and MovieArrayListTester. Each of them helps you run the code for the inputs provided.

Within each class is a SimpleMap data member, which maps a string to a pointer to an object. The string is the variable name, and the pointer is the object associated with the variable name. Whenever you want to assign a pointer to a variable name, you can call the map function.

For example, if you look at the MovieTester code, you can see calls like:

   Movie *ptr = new Movie();  // creates a new Movie object
   map( str, ptr );  // maps the string to the new object
operator[] has been overloaded so you can access the object in a "convenient form". If you are in the MovieTester class, you access the object as:
   (*this)[ varName ]
For example, to call setEarnings()
   (*this)[ varName ].setEarnings( value );
Things becomes a little tougher in MovieSortedListTester. You can use the same technique to access a MovieSortedList object. However, you will also need to access Movie objects. Those can be accessed by using operator[] on the movieLookup object, as in:
  Movie & m = movieLookup[ varName ];
Notice that this creates an "associative" array, where the index is a string (the variable name) instead of an int.

Read the MovieTester code to get a better idea of what's going on.

The only class that's not partly implemented for you is MovieArrayListTester. Use MovieSortedListTester to guide you on how to implement the class. In particular, use a SimpleMap to map a string to MovieArrayList pointer objects. A good way to start is to copy the code for MovieSortedListTester, and change the name to MovieArrayListTester and make appropriate changes.

InputTokenizer

(NEW)
The InputTokenizer classes are used by main(). Basically, you don't really have to know how it works, but if you do, this is what it does. It takes an input separated by delimiter and breaks them up into "tokens" or words. The delimiter (or separator) can either be blank spaces, or possible blank spaces followed by a delimiter character (say, a comma), followed by possibly blank spaces.

In this project, the tokenizer will split based on blank spaces, which will be blanks, newlines, and tabs (though no tabs should appear).

The tokenizer will read until a "keyword" (in this case </cmmd>. It tokenizes up to, but not including the keyword. The keyword is removed from the input.

Spaces are placed so that each "word" is considered a token. Spaces appear as described by the BNF below, and roughly correspond to how a compiler would break up words in a program (except the spaces are there for making it easier to break up to tokens).

If you write your own test files, you need to be careful to follow the spacing convention, otherwise, you may not get the correct answer.

The first token (at index 0), will always be the keyword MOVIE, SORTED, or ARRAY. The rest of the words in the command will be indexed up to, but not including, the ending </cmmd> keyword, and should work, even if the command spans more than one line.

The tokenizer has one very useful feature. When it sees a double quote, it reads up to the next double quote. It disposes of both quotes, but saves everything in between as one string.

For example, if you see:

   SORTED VERIFY x . contains ( "gone with the wind" ) </cmmd>
This will contain 8 tokens: { "SORTED", "VERIFY", "x", ".", "contains", "(", "gone with the wind", ")" }, indexed from 0 to 7. All the tokens will be saved as elements of a vector of string elements.

Primary Input/Output

(NEW)
Normally, there is a theme to the project. The "interesting" project will be project 4. The projects leading up to that are development of container classes in support of project 4. So, currently, the goal is to test and develop various classes.

To that effect, this project's goal is to write an automated test driver. In effect, it is a very simplistic interpreter for C++. It will allow you to declare methods, call methods, and determine whether a boolean function is true or false.

Input

The input will be a series of "commands", which will allow you to declare variables, run constructors, etc. Most of this has been implemented in a class called MovieTester.

Note: some of the non-terminals appear in the EBNF Tutorial. Go to the Tutorial section of the main webpage, and click on it.

Movie

The input format looks like:
      <start> := "<cmmdlist>" <multicmmd> <seps> "</cmmdlist>"
  <multicmmd> := [[ <seps> <command> ]]*
    <command> := "<cmmd>" <seps>
                    [[ <moviecmmd> | <srtdcmmd> | <arraycmmd> ]] 
                    "</cmmd>"
  <moviecmmd> := "MOVIE" <seps> [[ <moviedecl> | <moviepr> | 
                                  <movierun> | <movieverify> ]] <seps>
  <moviedecl> := "DECLARE" <seps> <var> 
                    [[ <seps> ( <mcopy> | <mconst> ) ]]?
      <mcopy> := "=" <seps> <var>
     <mconst> := "(" <seps> "string" <seps> "=" <seps> <dqstring>
                    [[ <seps> "," <seps> "int" <seps> "=" <seps> <digits> ]]?
                    <seps> ")"
    <moviepr> := "PRINT" <seps> <var>
   <movierun> := "RUN" <seps> <var> <seps> "=" <seps> <var>
<movieverify> := "VERIFY" <seps> <operator> <seps> <var> <seps> <var> |
                 "VERIFY" <seps> <operator> <movieget> <movieget>     |
                 "VERIFY" <seps> <var> <seps> "." <seps> "setEarnings"
                    <seps> "(" <seps> <digits> <seps> ")"
   <movieget> := <seps> <var> <seps> "." <seps> "getEarnings" <seps>
                    "(" <seps> ")"
   <operator> := "==" | "!=" | "<" | "<=" | ">" | ">=" 

<movieverify> := "VERIFY" <seps> <operator> 
                    ( <seps> <var> <seps> <var> |
                      <seps> <var> <seps> "." <seps> "getEarnings"
                      <seps> "(" <seps> ")" <seps> <var> <seps> "." 
                      <seps> "getEarnings" <seps> "(" <seps> ")" )
   <movierun> := "RUN" <seps> [ <movieassign> | <movieset> ]
<movieassign> := <var> <seps> "=" <seps> <var>
   <movieset> := <var> <seps> "." <seps> "setEarnings" <seps>
                 <lparen> <digits> <rparen>
     <mconst> := <lparen> <seps> <param> [ <seps> "," <seps> <param> ]+
                 <seps> <rparen>
      <param> := ( "string" <seps> "=" <seps> <dqstring> | 
                  "int" <seps> "=" <seps> <digits> )

Note: because of the width of the screen, some of these rules take one or more lines. Do NOT assume that this means there is a newline at the end of the line.

The input (see input file) is written using a format that's like HTML. In fact, it's written in a more generalized form called XML. This format is becoming increasingly popular way to record information in a standard way. In XML, you can create your own tags, or use tags developed by someone for their data.

In this case, you have a list of commands (called a command list). Each command starts with <cmmd> and ends in </cmmd>. Each command begins with one of three words: MOVIE, SORTED, ARRAY. A command that starts with MOVIE will handle primarily Movie objects. A command that starts with SORTED will primarily handle MovieSortedList and Movie. Finally, a command that starts with ARRAY will primarily handle MovieArrayList and Movie.

MOVIE commands can be broken down into four types: DECLARE, RUN, VERIFY, PRINT.

DECLARE allows you to declare a variable. You may assume:

You can declare a variable three ways.

You may assume that the copy constructor assigns to a valid variable (i.e., it's been declared earlier). You may assume the values have correct syntax for the constructors taking 1 or 2 arguments. Again, look at the input file for a better understanding.

RUN operations are methods that don't return true or false. Currently, there's only one such method that is supported: the assignment statement.

MOVIE RUN y = x

VERIFY operations fall into several categories. They are either methods that return true or false, as in setEarnings().

MOVIE VERIFY y . setEarnings ( 2000 )
Or they compare two movie variables using the relational operators you defined.
MOVIE VERIFY == x y
n You must handle all 6 relational operators. Or you can compare the earnings of movies, using all 6 relational operators.
MOVIE VERIFY == y . getEarnings ( ) x . getEarnings ( )

Finally, there is PRINT, which allows you to print a movie variable.

MOVIE PRINT x

Most of the methods are implemented in MovieTester. You just need to complete the implementation for the remainder of the relational operators. Only == and != has been implemented for you.

MovieSortedList

The following are BNF for MovieSortedList commands. All of there begin with the word, SORTED.
   <srtdcmmd> := "SORTED" <seps> [[ <srtddecl> | <srtdpr> | 
                                    <srtdrun> | <srtdverify> ]] <seps>
   <srtddecl> := "DECLARE" <seps> <var> 
                    [[ <seps> "=" <seps> <var> ]]?
     <srtdpr> := "PRINT" <seps> <var>
    <srtdrun> := "RUN" <seps> <var> <seps>
                    [[ <srtdassign> | <srtdclear> ]]
 <srtdassign> := "=" <seps> <var>
  <srtdclear> := "." <seps> "clear" <seps> "(" <seps> ")"
 <srtdverify> := "VERIFY" <seps> <var> <seps> [[ <svmethod> | <svlist> ]]
   <svmethod> :=  "." <seps> 
                    [[ <srtdcontain> | <srtdremove> |
                       <srtdupdate> | <srtdadd> ]] 
    <srtdadd> := "add" <seps> "(" <seps> <var> <seps> ")"
 <srtdupdate> := "update" <seps> "(" <seps> <var> <seps> ")"
 <srtdremove> := "remove" <seps> "(" <seps> <dqsrting> <seps> ")"
<srtdcontain> := "contains" <seps> "(" <seps> <dqsrting> <seps> ")"
     <svlist> := "<list>" 
                    [[ <seps> <dqstring> <seps> <digits> ]]* 
                    <seps> "</list>" 

   <svmethod> := <var> <seps> "." <seps> 
                    [[ <srtdcontain> | <srtdremove> |
                       <srtdupdate> | <srtdadd> ]]
<srtdassign> := <var> <seps> "=" <seps> <var>
 <srtdclear> := <var> <seps> "." <seps> "clear"
                             <seps> "(" <seps> ")"
   <srtdadd> := <var> <seps> "." <seps> "add"
                       <seps>  "(" <seps>
                       <var> <seps> ")"
<srtdupdate> := <var> <seps> "." <seps> "update"
                       <seps>  "(" <seps>
                       <var> <seps> ")"
<srtdremove> := <var> <seps> "." <seps> "remove"
                       <seps> "(" <seps> <dqsrting> <seps> ")"
<srtdupdate> := <var> <seps> "." <seps> "update"
                       <seps>  "(" <seps> <dqsrting> <seps> ")"

For a MovieSortedList, there are only two ways to declare: There are only a handful of RUN methods. There are four VERIFY methods: add(), remove(), update(), and contains(). add() and update() will take a Movie variable as its only argument. remove() and contains() will take a string written the non-proper format (i.e., written as "the lord of the rings" rather than "lord of the rings, the")

In addition, there is a verify list, which verifies the list elements. Here's an example:

<cmmd> SORTED VERIFY mList
  <list>
    "BATMAN" 3000
    " Go Go"  1000
    " RUN THERE"  2000
  </list>
</cmmd>
It will be SORTED, followed by VERIFY, followed by a valid variable name, followed by <list>, followed by 0 or more occurrences of a movie in double quotes, followed by the earnings.

The ordering is important. You must determine if mList contains BATMAN, Go Go, RUN THERE, in exactly that order, with the earnings 3000, 1000, 2000 for each movie. If mList contains fewer or more movies, or the earnings are different, or the order is different, then it fails to verify. Again, recall that movies are case-insentive, and two movies are equivalent based on the definition used by compare.

MovieArrayList (Typo fixed)

The following are BNF for MovieArrayList commands. All of there begin with the word, ARRAY.
   <arrcmmd> := "ARRAY" <seps> [[ <arrdecl> | <arrpr> | 
                                  <arrrun> | <arrverify> ]] <seps>
   <arrdecl> := "DECLARE" <seps> <var> 
                   [[ <seps> "=" <seps> <var> ]]?
     <arrpr> := "PRINT" <seps> <var>
    <arrrun> := "RUN" <seps> <var> <seps>
                   [[ <arrassign> | <arrclear> | <arrpush> ]]
 <arrassign> := [[ <arrpassign> | <arrmassign> ]]
<arrpassign> := "=" <seps> <var>
<arrmassign> := "[" <seps> <udigits> <seps> "]" <seps> "=" <seps>
                   [[ <var> |
                      <var> <seps> "[" <seps> <udigits> <seps> "]" ]]
  <arrclear> := "." <seps> "clear" <seps> "(" <seps> ")"
   <arrpush> := "." <seps> "pushBack" <seps> 
                   "(" <seps> <var> <seps> ")"
 <arrverify> := "VERIFY" <seps> <var> <seps> [[ <avmethod> | <avlist> ]]
  <avmethod> := "." <seps> [[ <arrresize> | <arrpop> ]]
 <arrresize> := "resize" <seps> "(" <seps> <digits> <seps> ")"
    <arrpop> := "popBack" <seps> "(" <seps> ")"
    <avlist> := "<list>" 
                   [[ <seps> <dqstring> <seps> <digits> ]]* 
                   <seps> "</list>" 

<arrpassign> := <var> <seps> "=" <seps> <var>
<arrmassign> := <var> <seps> "[" <seps> <udigits>
                          <seps> "]" <seps> "=" 
                          ( <var> | <var> <seps> "[" <seps> 
                                    <udigits> <seps> "]"
  <arrclear> := <var> <seps> "." <seps> "clear"
                             <seps> "(" <seps> ")"
   <arrpush> := <var> <seps> "." <seps> "pushBack"
                       <seps>  "(" <seps>
                       <var> <seps> ")"
  <avmethod> := <var> <seps> "." <seps> 
                   ( <arrresize> | <arrpop> )
 <arrresize> := <var> <seps> "." <seps> "resize"
                       <seps>  "(" <digits> ")"
    <arrpop> := <var> <seps> "." <seps> "popBack"
                       <seps>  "(" <seps> ")"

The DECLARE and PRINT operations are the same as in MovieSortedList. RUN operations can be an assignment statement (as before), a call to clear() as before, or a call to a pushBack() where pushBack takes a movie variable as argument. It can also call an assignment statement. Either you can assign one MovieArrayList variable to another, or you can use the operator[] to access a movie object in a MovieArrayList object and set it to either a previously declared Movie variable or to a movie object in the some MovieArrayList object.

Here are some possibilities:

  ARRAY RUN x = y
  ARRAY RUN x [ 1 ] = movie1
  ARRAY RUN x [ 1 ] = y [ 0 ]
where x and y are MovieArrayList objects and movie1 is a Movie object. You may assume all such objects have been declared using a DECLARE operation.

The VERIFY operations apply to methods resize() which takes an int value for a parameter (possibly, invalid) and pop() which has no parameters. And, just as in the MovieSortedList BNF, you can check to see if a movie array contains certain movies and earnings:

<cmmd> ARRAY VERIFY aList
  <list>
    "BATMAN" 3000
    " Go Go"  1000
    " RUN THERE"  2000
  </list>
</cmmd>
Again, the order matters. In order for this array list to verify, you must have 3 elements, with "BATMAN"," Go Go", and " RUN THERE" in that order, plus the three earnings in that order. It is possible for a movie to be called "NONE", and show up multiple times (because of the resize() operation), so keep that in mind.

Output

For each command, there is a corresponding output. This is how the output should appear:
<output> := <line>
              [[ ["Input: " <digits> <endl> <out> <line>]+ |
                "EMPTY COMMAND LIST" <endl> <line> ]]
              <endl>
              <stats>
<line> ::== "----*----*----*----*----*----*----*----*" <endl>

<output> := <line>
              [[ [ "Input: " <digits> <endl> <out> 
                ----*----*----*----*----*----*----*----*" <endl> ]+ |
                "EMPTY COMMAND LIST" <endl> <line> ]]
              <endl>
              <stats>

<stats> := "Inputs verified: " [[ "NONE" |
                                   <udigits> [", " <udigits>]* ]] <endl>
             "Total positive inputs: " <udigits> <endl>
             "Inputs not verified: " [[ "NONE" |
                                   <udigits> [", " <udigits>]* ]] <endl>
             "Total negative inputs: " <udigits> <endl>
             "Total inputs checked: " <udigits> <endl>

<stats> := "Inputs verified: " [[ "NONE" | <udigits> [" ," <udigits>]+ ]] <endl>
             "Total positive inputs: " <udigits> <endl>
             "Inputs not verified: " ( "NONE" | <udigits> [ " ," <udigits> ]+ ) <endl>
             "Total positive inputs: " <udigits> <endl> <endl>
             "Total inputs checked: " <udigits> <endl>
There is a leading line, plus "Input: " and the input number. The input number starts at 1, and continues up. Thus, if there are n commands, the inputs are numbered 1 to n.

The output of each command is separated by a line.

If there are no commands, print "EMPTY COMMAND LIST" followed by a newline, followed by the fancy line.

After the list are statistics that print the results of commands with the word VERIFY appearing as the second word.

Movie

The output for DECLARE for a movie should be:
<mdeclareout> := "MOVIE DECLARE " <var> <endl>
where the variable name is printed.

The output for RUN for a movie should be:

<mrunout> := "MOVIE RUN " <var> " assign" <endl>
<mrunout> := "MOVIE RUN " <var> " " ( "assign" | "setEarnings" ) <endl>
where the variable name is printed, and "assign" is printed if it's an assignment statement or "setEarnings" is printed if that method is called.

The output for PRINT should be:

======>(UPDATED BNF) (on Feb 19). No longer prints "Title:".

<mprintout> := "MOVIE PRINT " <var> <endl>
                  <dquote> <title> <dquote> 
                  "   Earnings: " <udigits> <endl>
    <title> := <word> [<blank> <word>]* [", " <word>]?
It should print the variable name. On the second line, there should be the "Title: ", then a double quote, then the proper title, then a double quote, then 3 spaces, then "Earnings: ", then the earnings and a newline.

The output for VERIFY should be:

(NEW BNF)

   <mverifyout> := "MOVIE VERIFY " <var> " " [[ <mverifyout> |
                                                <mverifyoutset> ]]
<mverifyoutset> := "setEarnings " [[ "IS SUCCESSFUL" | "FAILS" ]] <endl>
 <mverifyoutop> := <var> " " <op> " " [[ "IS SUCCESSFUL" | "FAILS" ]] <endl>
           <op> := "==" | "!=" | "<" | "<=" | ">" | ">=" 

<mverifyoutset> := "MOVIE VERIFY " <var> 
                      "setEarnings " [[ "IS SUCCESSFUL" | "FAILS" ]] <endl>
 <mverifyoutop> := "MOVIE VERIFY " <var> " " <var> " " 
                 <op> " " [[ "IS SUCCESSFUL" | "FAILS" ]] <endl>
It should print out "IS SUCCESSFUL" if the comparison returns true, and FAILS, if it returns false.

(NEW) The first var is the name of the first variable, and the second var is the name of the second variable, when using relational operators. For setEarnings(), it's the name of the variable which setEarnings() is being applied to.

MovieSortedList

The output for DECLARE for a MovieSortedList should be:
<sdeclareout> := "SORTED DECLARE " <var> <endl>
where the variable name is printed.

The output for RUN for a MovieSortedList should be:

<srunout> := "SORTED RUN " <var> " " [[ "assign" | "clear" ]] <endl>
where the variable name is printed, and "assign" is printed if it's an assignment statement or "clear" is printed if that method is called.

The output for PRINT should be:

<sprintout> := "SORTED PRINT " <var> <endl>
                  [[ ["(" <udigits> ") " <dquote> <title> <dquote>
                        "   Earnings: " <udigits> <endl>]+ |
                     "THERE ARE NO MOVIES IN THIS LIST" <endl> ]]
    <title> := <word> [<blank> <word>]* [", " <word>]?

<sprintout> ::== "SORTED PRINT " <var> <endl>
                  ( [ <lparen> <udigits> <rparen>
                      " " <dquote> <title> <dquote> 
                    "   Earnings: " <udigits> <endl> ] +
                    "THERE ARE NO MOVIES IN THIS LIST" <endl>
This should print out "SORTED PRINT ", followed by the name of the variable being printed, then a new line, then a list of movies, as shown in the print() method of MovieSortedList, or "THERE ARE NO MOVIES IN THIS LIST", if there are 0 movies in the list.

The output for VERIFY should be:

(NEW BNF)

<sverifyout> := "SORTED VERIFY " <var> <smethod> [[ "IS SUCCESSFUL" |
                                                    "FAILS" ]] <endl>
   <smethod> := " add " | " remove " | " contains " | " update " | " LIST "
It should print out "IS SUCCESSFUL" if the method call returns true, and FAILS, if it returns false. <smethod> refers to the method that's being tested (e.g., add, remove, etc), except for "LIST", which is when you check if the movie contains the list shown between <list> and </list> (see sample input).

(NEW)

Now prints out variable name before the method.

MovieArrayList

The output for DECLARE for a MovieArrayList should be:
<adeclareout> := "ARRAY DECLARE " <var> <endl>
where the variable name is printed.

The output for RUN for a movie should be:

<arunout> := "ARRAY RUN " <var> [[ " assign" | " assign MOVIE" | " pushBack" |
                                   " clear" ]] <endl>

<mrunout> := "ARRAY RUN " <var> " "
                   ( "assign" | "assign MOVIE" | "setEarnings" ) <endl>
where the variable name is printed.

The output for PRINT should be:

<aprintout> := "ARRAY PRINT " <var> <endl>
                  [[ ["(" <udigits> ") " <dquote> <title> <dquote>
                        "   Earnings: " <udigits> <endl>]+ |
                     "THERE ARE NO MOVIES IN THIS LIST" <endl> ]]
    <title> := <word> [<blank> <word>]* [", " <word>]?


<aprintout> ::== "ARRAY PRINT " <var> <endl>
                  ( [ <lparen> <udigits> <rparen>
                      " " <dquote> <title> <dquote> 
                    "   Earnings: " <udigits> <endl> ] +
                    "THERE ARE NO MOVIES IN THIS LIST" <endl>
This is the same format as for SORTED PRINT.

The output for VERIFY should be:

(NEW BNF)

<averifyout> := "ARRAY VERIFY " <var> <amethod> [[ "IS SUCCESSFUL" |
                                                   "FAILS" ]] <endl>
   <amethod> := " popBack " | " resize " | " LIST "
It should print out "IS SUCCESSFUL" if the method call returns true, and FAILS, if it returns false. <smethod> refers to the method that's being tested (e.g., pop, resize), except for "LIST", which is when you check if the movie contains the list shown between <list> and </list> (see sample input).

(NEW)

Now prints out variable name before the method.

Style Guide

(NEW)

A style guide will be posted. In the meanwhile, read the background reading on documentation, and follow the style guide given in Project 0.

In addition, to the documentation specifications, here are several style rules to follow.

  1. Be consistent in using Underscore or Uppercase style. (The functions are written in Uppercase style, but you can use variables in Underscore, if you wish). Uppercase style says that every "word" except the first should have its first letter capitalized, as in "getProperTitle". Underscore has all letters in lowercase, but separated by underscores as in "get_proper_title". You should leave the public method names alone, but if you declare your own variables or private methods, you can use that style.

  2. Put a space after each comma and semicolon. For example, instead of:
      for (int i=0;i<n;i++)
         func(arg1,arg2,i);
    
    write it as:
      for (int i=0; i<n; i++)
         func(arg1, arg2, i);
    
    Notice the single space after each comma and semicolon.

  3. For binary operators such as "=", "==", "<", put a blank sapace before and after. So, instead of
      for (int i=0; i<n; i++)
        if (i!=3)
          func(arg1, arg2, i);
    

    You would write:

      for (int i = 0; i < n; i++)
        if (i != 3)
          func(arg1, arg2, i);
    
Notice the single space before and after the "=", "<", and "!=".

README

(NEW)

In the README, indicate which classes you implemented the copy constructor, assignment operator, and destructor. For example:

Implemented copy constructor, assignment operator, and destructor
for following classes
------------------------------------------------------------------
Foo

Didn't implement it for
-----------------------
Bar
Briefly explain why you implemented or didn't implement for the classes listed.

Second, indicate which kind of "locate()" method you used. These are the four choices. If you picked something else, describe the algorithm.

This should be placed under a section that is labelled as follows:
How I implemented locate()
--------------------------
// fill in stuff here
Finally, write the pseudocde for your "add" method. Indicate the running time for ad
Pseudocode for add
------------------
// fill in stuff here
Make sure you label the README file so we know who you are, which section, etc.

Test Drivers, Revisited

(NEW)

Initially, you were told to create separate files for test drivers. However, this makes it inconvenient for compiling. So, instead, create a static method called EXACTLY runTestDriver() which takes no arguments. Add this to the PUBLIC section of your class declaration (in the .h file), as in:

public:
   static void runTestDriver();
All the code you used to test your class should go into this method in the corresponding .cpp file. If your file used helper methods, e.g., testDriverCheckCopy(), then those should be static methods. However, these methods should start with the word "testDriver", so we can tell they are methods used by your test driver. Thus:
   static void testDriverCheckCopy(); // checks copy cons
This can be placed in public or private section of your class header file (preferably, private).

Verifier Methods

Make sure to read the background on "documentation" (a link appears earlier).

For this project, it will be optional to have verify methods. These are used to test preconditions, postconditions, and class invariants.

This is how you would use it, if you wanted to. First, declare a private variable called "checkContract" and have methods that will set it to true or false (setCheckContract(), which takes a bool argument). Then, in you might have code that looks like:

void pop()
{
  if ( checkContract )
    if ( popPrecond() && stackClassInvariant() )
       cout << "POP PRECONDITION SUCCESSFUL" << endl;
    else
       cout << "POP PRECONDITION FAILS" << endl;

// code

  if ( checkContract )
    if ( popPostcond() && stackClassInvariant() )
       cout << "POP POSTCONDITION SUCCESSFUL" << endl;
    else
       cout << "POP POSTCONDITION FAILS" << endl;    
}
where popPrecond(), popPostcond(), stackClassInvariant() are boolean methods which return true or false, and check for whether code is implemented correctly.

You could cause the program to exit if the condition fails, forcing the programmer to fix it as errors occur.

The checkContract variable, when true, is used to check the preconditions, postcondition, and class invariants. However, such checking is often "expensive" (meaning, slow). So, it's handy to have a way to turn it off.

Again, this is optional, and should only be done when the project is completed. However, it's usually best to think of these invariants AS you develop the class, and put the code as methods are being developed. Doing it after the fact tends to defeat the purpose (although if the tests fail, you know you haven't tested enough).

Debugging Hints

When you write the code, obviously, use a test driver. You need to submit it anyway, so use it.

Also, for MovieArrayList, it's a good idea to print a message indicating you've gone out-of-bounds, if the index is out-of-bounds. Notice that regular arrays won't tell you such things.

How to Submit Your Project

In order to successfully submit your project, it must pass the primary input and produce the primary output. The primary input will be sent to your project using input redirection.

   p1 < primary.input
Your program MUST produce the executable p1, EXACTLY, when the command "make" is run with no arguments. Thus, you must use a makefile named exactly "Makefile".

We will use "diff -bwi" to test your code. This ignores case, treats N blanks as 1 blank, treats N blank lines as 1 blank line. We will also strip all blank lines from your input when matching to ours. However, diff is sensitive to punctuation, number of dashes, etc. so you should attempt to make your output match ours as closely as possible otherwise you may not be able to submit your program. If this is the case (that your program does not submit) you must fix your code until the output it produces matches that of the primary output. Note: "hardcoding" output is a violation of the University's Code of Academic Integrity.

To submit your project you must first combine the following files (and only these files) into a single tar file using the Unix tar command:

You may name your tarfile anything you want, but p1.tar is the suggested name.

NOTE! You should make a backup copy of all your files BEFORE attempting to create your tarfile!!!! You have been warned.

After creating the tar file you should submit that one file using the following command:

submit p1.tar 1
where p1.tar can be replaced by whichever tar file you have created, and 1 refers to the current project,

See the class syllabus for policies concerning email
Last Modified: Tue Feb 12 19:48:57 EST 2002
left up down right home

Web Accessibility