stack.h

00001 //
00002 // Stack implemented using a dynamically allocated using a linked list
00003 //
00004 
00005 #ifndef STACK_H
00006 #define STACK_H
00007 
00008 #include <stdexcept>
00009 #include <new>
00010 #include <string>
00011 #include "node.h"
00012 
00013 using namespace std;
00014 
00015 /*=========================================================================*/
00016 
00024 class StackEmpty : public runtime_error {
00025   public:
00026     StackEmpty() : runtime_error( "stack empty" ) {}
00027     StackEmpty( const string &what ) : runtime_error( what ) {}
00028 };
00029 
00030 /*=========================================================================*/
00031 
00040 template <typename T>
00041 class Stack {
00042 
00043   public:
00044     Stack();
00045     Stack( const Stack & ) throw ( bad_alloc );
00046     ~Stack();
00047     bool empty() const;
00048     unsigned size() const;
00049     void clear();
00050     void push( const T & ) throw ( bad_alloc );
00051     T pop() throw ( StackEmpty );
00052     T &top() const throw ( StackEmpty );
00053     const Stack<T> &operator=( const Stack<T> & ) throw ( bad_alloc );
00054   
00055   private:
00056     unsigned sz;
00057     Node<T> *contents;
00058 
00059 }; // Stack class
00060 
00065 template <typename T>
00066 Stack<T>::Stack()
00067 {
00068   sz = 0;
00069   contents = 0;
00070 } // Stack<T>::Stack
00071 
00079 template <typename T>
00080 Stack<T>::Stack( const Stack<T> &s ) throw ( bad_alloc )
00081 {
00082   sz = 0;
00083   contents = 0;
00084   *this = s;
00085 } // Stack<T>::Stack
00086 
00091 template <typename T>
00092 Stack<T>::~Stack()
00093 {
00094   clear();
00095 } // Stack<T>::~Stack
00096 
00103 template <typename T>
00104 bool Stack<T>::empty() const
00105 {
00106   return (contents == 0);
00107 } // Stack<T>::empty
00108 
00115 template <typename T>
00116 unsigned Stack<T>::size() const
00117 {
00118   return sz;
00119 } // Stack<T>::size
00120 
00125 template <typename T>
00126 void Stack<T>::clear()
00127 {
00128   Node<T> *current = contents;
00129   while (contents != 0) {
00130     contents = contents->getNextPtr();
00131     delete current;
00132     current = contents;
00133   } // while
00134   sz = 0;
00135   contents = 0;
00136 } // Stack<T>::clear
00137 
00145 template <typename T>
00146 void Stack<T>::push( const T &item ) throw ( bad_alloc )
00147 {
00148   Node<T> *newNode = new Node<T>( item );
00149   newNode->setNextPtr( contents );
00150   contents = newNode;
00151   sz++;
00152 } // Stack<T>::push
00153 
00161 template <typename T>
00162 T Stack<T>::pop() throw ( StackEmpty )
00163 {
00164   if ( empty() )
00165     throw StackEmpty( "pop: stack empty" );
00166   Node<T> *ptr = contents;
00167   contents = contents->getNextPtr();
00168   T value = ptr->getObject();
00169   delete ptr;
00170   sz--;
00171   return value;
00172 } // Stack<T>::pop
00173 
00181 template <typename T>
00182 T &Stack<T>::top() const throw ( StackEmpty )
00183 {
00184   if ( empty() )
00185     throw StackEmpty( "top: stack empty" );
00186   return contents->getObject();
00187 } // Stack<T>::top
00188 
00197 /*
00198  * Overloaded assignment operator for memberwise copy
00199  * const return avoids ( s1 = s2 ) = s3
00200  */
00201 
00202 template <typename T>
00203 const Stack<T> &Stack<T>::operator=( const Stack<T> &s ) throw ( bad_alloc )
00204 {
00205   if ( this != &s ) {  // check for self-assignment
00206     if ( !empty() )
00207       clear();
00208     sz = s.sz;
00209     Node<T> *meptr = 0, *sptr = s.contents;
00210     while ( sptr != 0 ) {
00211       if ( meptr == 0 )
00212         contents = meptr = new Node<T>( *sptr );
00213       else {
00214         meptr->setNextPtr( new Node<T>( *sptr ) );
00215         meptr = meptr->getNextPtr();
00216       } // else
00217       sptr = sptr->getNextPtr();
00218     } // while
00219   } // if
00220   return *this; // enables x = y = z
00221 } // Stack<T>::operator=
00222 
00223 #endif // STACK_H
00224 

Generated on Wed Sep 12 10:34:23 2007 by  doxygen 1.5.1