CS 250 Computer Programming and Problem Solving - FALL 1998 

[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]


A New Sequential List Class


Why change the Tlist class in the book?

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;
}


// complete source code here

 


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();
   }
}

Copyright chris wild 1998.
For problems or questions regarding this website contact [Chris Wild (e-mail:wild@cs.odu.edu].
Last updated: November 09, 1998.