CS 250 Computer Programming and Problem Solving - FALL 1998 |
---|
[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]
So, here I go again changing things - Lets' build a new class called "SeqList" since it is best for handling sequentially built and accessed lists.
//************************************************** // Template class for SeqList - Sequential List // This list supports efficient access to either end of the list // for adding new elements and sequential iteration over the list // Uses exception handling (NoCurrentValue) for the error of getting an element // that does not exist from the list. This can happen for tow reasons // 1) list is empty // 2) current is set to position before beginning of list // Reset must be followed by Advance to get the first element // This decision was made to allow InsertAfter to be able to // insert at the beginning of the list // and to allow the following style of list traversal // myList.Reset(); // while(myList.Advance()) { // cout << myList.Get(); // // This implementation uses a linked list so also // define a LinkNode class // // Programmer: Chris Wild // Date: Novemeber 8, 1998 //************************************************** class NoCurrentValue { // exception class public: friend ostream & operator <<( ostream & os, const NoCurrentValue & nc ) { os << "List exception: No current value.\n"; return os; } }; //**** define a LinkNode class // NO MORE friends template <class T> class LinkNode { public: LinkNode(); //POST: Value uses default constructor // next is set to NULL LinkNode( const T & val ); //PRE: T has a copy constructor //POST: value set to val, next set to NULL LinkNode<T> * GetNext() const; void SetNext(LinkNode<T> * theNext); //PRE: theNext is either NULL or points to a LinkNode object T GetValue() const; //PRE: assumes copy constructor void SetValue(const T & theValue); // PRE: assumes assignment operator private: T value; // data stored in node LinkNode * next; // points to next node }; // A singly linked list of LinkNode objects. template <class T> class SeqList { friend ostream & operator <<(ostream &, const SeqList<T> &); public: SeqList(); ~SeqList(); bool Advance(); // POST: Return false if current position is already at // the end of the list; otherwise, increment // current and return true. // can be used as condition in loop since // GoFirst sets current to dummy node, first advance // will advance to first "real" node void Clear(); // POST: Remove all nodes from list. T Get() const; // PRE: current position has a value // otherwise throws NoCurrentValue exception // POST: Get the data at the current position. void GoLast(); // POST: Set current to the last node in the list. void ReSet(); // POST: Set current to position before first element in list // Should Advance first beforing getting data. // Or you can InsertAfter to put new elemeent at the beginning of list void InsertAfter( const T & nodeVal ); // Post: Insert new node after current one. // For empty list, or after Reset, inserts at the beginning of list bool IsEmpty() const; // Return true if the list is empty; otherwise, // return false. void Replace( const T & newVal ); // PRE: current position has a value // otherwise throws NoCurrentValue exception // POST: Replace the data in the current node. private: LinkNode<T> * head; // dummy head node LinkNode<T> * tail; // points to last node LinkNode<T> * current; // current position }; //............LinkNode<T> class ............ template <class T> LinkNode<T>::LinkNode( ) { next = 0; } template <class T> LinkNode<T>::LinkNode( const T & val ): value(val) { next = 0; } template <class T> LinkNode<T> * LinkNode<T>::GetNext() const { return next; } template <class T> void LinkNode<T>::SetNext(LinkNode<T> * theNext) { next = theNext; } template <class T> T LinkNode<T>::GetValue() const { return value; } template <class T> void LinkNode<T>::SetValue(const T & theValue) { value = theValue; } template <class T> ostream & operator <<( ostream & os, const LinkNode<T> & N ) { os << N.value << ','; return os; } //............ SeqList<T> class ............ template <class T> SeqList<T>::SeqList() { head = new LinkNode<T>; head->SetNext(NULL); tail = head; current = head; } template <class T> SeqList<T>::~SeqList() { Clear(); delete head; } template <class T> bool SeqList<T>::Advance() { if( current->GetNext() != NULL ) { current = current->GetNext(); return true; } return false; } template <class T> void SeqList<T>::Clear() { current = head->GetNext(); while( current != NULL ) { head->SetNext(current->GetNext()); delete current; current = head->GetNext(); } current = head; tail = head; } template <class T> bool SeqList<T>::IsEmpty() const { return head == tail; } template <class T> T SeqList<T>::Get() const { if( current == head ) throw NoCurrentValue(); return current->GetValue(); } template <class T> void SeqList<T>::GoLast() { current = tail; // much more efficient than book's } template <class T> void SeqList<T>::ReSet() { current = head; } template <class T> void SeqList<T>::InsertAfter( const T & nodeVal ) { LinkNode<T> * p = new LinkNode<T>( nodeVal ); p->SetNext(current->GetNext()); current->SetNext(p); if(current == tail) tail = p; // new tail current = p; } template <class T> void SeqList<T>::Replace( const T & newVal ) { if( current == head ) throw NoCurrentValue(); current->SetValue(newVal); } template <class T> ostream & operator <<( ostream & os, const SeqList<T> & S ) { if( S.IsEmpty()) return os; LinkNode<T> * p = S.head->GetNext(); while( p != NULL ) { os << *p; p = p->GetNext(); } os << endl; return os; }
Demonstrate use of Exception Handling (See discussion of Exception Handling here)
//******************************************** // Read a file of Persons and create a list // Uses template class // // Programmer: Chris Wild //******************************************** #include "person.h" #include "tlist.h" void main() { SeqList<Person> myList; Person someBody; ifstream aFile("persons.txt"); try { myList.Get(); } catch(const NoCurrentValue & nv) { cerr << "List is empty test case\n"; cerr << nv; // print error // could abort here - it's up to us to decide - let's continue } while(aFile >> someBody) { myList.InsertAfter(someBody); } myList.ReSet(); try { myList.Get(); } catch(const NoCurrentValue & nv) { cerr << "after Reset - no current value to get\n"; cerr << nv; // print error // could abort here - it's up to us to decide - let's continue } while(myList.Advance()) { cout << myList.Get(); } }