Project 1

Assigned Sept. 11, 2000
Due Sept. 25, 2000


Background

Abstract Data Types (ADT) 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. It will also give you additional experience in designing and implementing a solution in response to a set of requirements.

You will get a chance to see how exceptions can be used to handle error situations.

You will write a Makefile, include headers from multiple directories, and compile code from multiple directories. These are commonly used techniques in industry, so they're worth learning for future reference.


Description

Operations on files full of information items are a common necessity in many kinds of computer applications. One such application is selection and retrieval of records from a database. An example database might hold a class list or hold list for this class, with each student record giving a name, major, year, id#, email address, and date added. An instructor might want to select groups of students out of the database for particular consideration (for instance, seniors off the hold list). This project gives you the opportunity to implement a simple generic database class. "Project Organization" handout.

Here are your tasks:

  1. Read and understand the text description of the string ADT and its C++ implementation in Appendix B. Code for string is available to you in the GL directory:
    /afs/umbc.edu/users/r/h/rheingan/pub/CMSC341/
    
  2. Implement the Student class. The header file for the class is given below. You may add any private member functions you deem necessary, but you may not modify the public interface, and you may not modify the private data members for this class. You must place the header file for the student class and its implementations in separate files named Student.H and Student.C
  3. Implement the Database ADT as a C++ class. The header for this class appears below. You may not change the public interface to the file. You must place the header file in a file named Database.H, and the implementation must be in a file named Database.C
    template <class Comparable> 
    class Database {
    private:
      vector<Comparable> _data;
      int                _nrecs;
    public:
      // big 4
      Database();
       Database(string str);       //passing a file name as parameter
      Database(const Database &);
      ~Database();
      const Database & operator=(const Database &);
    
      //added PUBLIC functions
    
      void sort(int direction, int field_nr);
      void merge(string dbname);
      Database & select(int field_nr, int criterion, string value);
      
      void remove(int field_nr, int criterion, string value);
      void print(ostream & out);
    };
    

  4. Write your own main program, named Proj1.C, to process command line arguments and make appropriate calls to your Database class. The database program syntax is the following:
    db [<cmd> <arg list>]* <db file>

    Specifically, the arguments are a list of zero or more command and argument-list pairs and the name of the file containing the database. Items on the command line are separated by tabs. When multiple commands are given, they should be executed in order, with the result database of the first becoming the input database for the next. If no commands are given, the program should print the contents of the input database.

    The commands are:

    • sort [+|-] <field #> : sort the records in the database on the indicated field in non-decreasing (+) or non-increasing (-) order.
    • merge   <new db file> : add records from another database file
    • select   <field #> [=|<|>]  <value> : select records where the value in the indicated field meets the given criterion (i.e., equal to, less than, or greater than the given value).
    • remove   <field #> [=|<|>]  <value> : delete records where the value in the indicated field meets the given criterion (i.e., equal to, less than, or greater than the given value).

    For example, the command

    db sort + 1 some.db
    reads the database in from the file 'some.db', sorts the records in order of increasing value of the first field, and prints the result. While the command
    db select 3 = CMSC sort + 4 hold.db
    selects all records belonging to CS majors, sorts them by year (field 4), and prints the result.

  5. Write a makefile. You can copy the file
    /afs/umbc.edu/users/r/h/rheingan/pub/CMSC341/Proj1/Makefile
    
    and modify it as needed.

  6. Use the definition of SetException provided in the files
    /afs/umbc.edu/users/r/h/rheingan/pub/CMSC341/Proj1/SetException.H
    
      and
    /afs/umbc.edu/users/r/h/rheingan/pub/CMSC341/Proj1/SetException.C
    

    Note: There is no need to copy these files to your own directory. Your makefile must access the files from the directory in which they are provided. Do not submit either of the SetException files.
Note that your class designs must handle all exceptional situations. For example, what will you do if a field index is out of bounds? Document and implement your approaches appropriately. In some cases, your only choice will be to throw an exception. In other cases, you might choose a different approach. Error handling is often the most significant and time-consuming part of programming. Think about your choices carefully.

C++ Exceptions

C++ exceptions are used by the text in various places. Perhaps the first use is on page 74 in the retrieve method. Since you will be seeing exceptions throughout the course, this project will give you some easy experience with them. The particular exception you will use is the SetException provided to you. The text defines a few other exceptions such as Underflow, Overflow, OutOfMemory, and BadIterator. You will not be using these in this project, but you will see them used in the text.

An exception can be "thrown" at any point in a program when an exceptional situation occurs. For example, an Overflow exception might be thrown when a quotient has a denominator of zero. An exception is thrown by using the syntax "throw exception".  Typical code for Overflow would be:

       if (denom == 0)
          throw Overflow()
       else
          quotient = numer/denom;

When an exception is thrown, the normal flow of control is terminated while a suitable "catcher" is sought along the calling sequence. For example, part of your implementation might look like this:

      bool Database::remove (Record & x) {
         if (isEmpty()){
         string ErrMessage = "Attempt to remove record from empty database";
         throw SetException(ErrMessage);
	 }
      // otherwise, continue processing  
A function that calls remove might check for an empty database beforehand, or it might have code like this:
     try {
     
          Database1.remove( somerecord);
	 }
     catch (SetError & Exceptn){
         cerr << "Exception:" << Exceptn.errorMsg() << endl;
	 }
What happens when the call to remove is made on an empty database is that remove throws an exception. As the call is inside a "try" block, control passes to the catch block that follows, which then deals with the exception. If there were no enclosing try-catch blocks, the exception would not be caught, and execution would terminate.

For this project, all that you need to deal with is throwing appropriate error conditions.


the Student class declaration


enum yr {unspecified,freshman, sophomore, junior, senior, grad};

class Student {
 private:
  string _name;
  string _major;
  yr     _yr; 
  int    _idNr;
  string _emailAddr;
  string _date;
 public:
  //big 4
  //constructors
  Student();
  Student(string name, string major, yr Year, int IdNr, string 
	  EmailAddr, string Date);
  Student (const Student &);

  //destructor
  ~student();

  //assignment
  const Student & operator=(const Student &);
  
  //Accessors
  string getName() const;
  string getMajor() const;
  yr getLevel() const;
  int getIdNr()const;
  string getEmailAddr()const;
  string getStudentDate()const;

  //Mutators 
  void changeName(const string & NewName);
  void setMajor(const string & NewMajor );
  void setLevel(int NewLevel);
  void setIdNr( int newIdNr);
  void setEmailAddr(const string & newID);
  void setStudentDate(const string & newDate);

  //output function
  friend ostream & operator <<(const ostream & O, const Student & S);
}; 

Grading and Academic Integrity

Project grading is described in the Project Policy handout. Please remember that you must provide good documentation as described in the

Cheating in any form will not be tolerated. Please re-read the Project Policy handout for further details on honesty in doing projects for this course.

Remember, the due date is firm. Submittals made after midnight of the due date will not be accepted. Do not submit any files after that time.


Files To Be Submitted

You should submit only the files you have written, and a makefile. The files to be submitted are: Please do not submit any of the files provided to you such as SetException.C, etc.

Submit the files using the procedure given to you for your section of the course.


Sample Output

Sample output will be available for your study. Stay tuned.

A copy of the executable will be available for you to try out. Stay tuned.