/*-- DStackT.h ------------------------------------------------------------- This header file defines a template for a Stack data type. StackElement is a type parameter received from a client program. Basic operations: constructor: Constructs an empty stack copy constructor: Makes a copy of a stack destructor: Deallocates memory allocated by constructor = : Assignment operator empty: Checks if a stack is empty push: Modifies a stack by adding a value at the top top: Accesses the top stack value; leaves stack unchanged pop: Modifies stack by removing the value at the top << and display: Displays all the stack elements Class Invariant: 1. The stack elements (if any) are stored in positions 0, 1, . . ., myTop of myArray. 2. -1 <= myTop < myCapacity --------------------------------------------------------------------------*/ #include #include #ifndef DSTACKT #define DSTACKT template class Stack { public: /***** Function Members *****/ /***** Constructors *****/ Stack(int numElements = 128); /*------------------------------------------------------------------------ Construct a Stack object. Precondition: None. Postcondition: An empty Stack object has been constructed (myTop is initialized to -1 and myArray is an array with numElements (default 128) elements of type StackElement). -----------------------------------------------------------------------*/ Stack(const Stack & original); /*------------------------------------------------------------------------ Copy Constructor Precondition: original is the stack to be copied and is received as a const reference parameter. Postcondition: A copy of original has been constructed. ------------------------------------------------------------------------*/ /***** Destructor *****/ ~Stack(); /*----------------------------------------------------------------------- Class destructor Precondition: None Postcondition: The dynamic array in the stack has been deallocated. ------------------------------------------------------------------------*/ /***** Assignment *****/ const Stack & operator=( const Stack & rightHandSide); /*------------------------------------------------------------------------ Assignment Operator Precondition: rightHandSide is the stack to be assigned and is received as a const reference parameter. Postcondition: The current stack becomes a copy of rightHandSide and a const reference to it is returned. ------------------------------------------------------------------------*/ bool empty() const; /*------------------------------------------------------------------------ Check if stack is empty. Precondition: None Postcondition: Returns true if stack is empty and false otherwise. -----------------------------------------------------------------------*/ void push(const StackElement & value); /*------------------------------------------------------------------------ Add a value to a stack. Precondition: value is to be added to this stack Postcondition: value is added at top of stack provided there is space; otherwise, a stack-full message is displayed and execution is terminated. -----------------------------------------------------------------------*/ void display(ostream & out) const; /*------------------------------------------------------------------------ Display values stored in the stack. Precondition: ostream out is open. Postcondition: Stack's contents, from top down, have been output to out. -----------------------------------------------------------------------*/ StackElement top() const; /*------------------------------------------------------------------------ Retrieve value at top of stack (if any). Precondition: Stack is nonempty Postcondition: Value at top of stack is returned, unless the stack is empty; in that case, an error message is displayed and a "garbage value" is returned. -----------------------------------------------------------------------*/ void pop(); /*------------------------------------------------------------------------ Remove value at top of stack (if any). Precondition: Stack is nonempty. Postcondition: Value at top of stack has been removed, unless the stack is empty; in that case, an error message is displayed and execution allowed to proceed. -----------------------------------------------------------------------*/ private: /***** Data Members *****/ int myCapacity, // capacity of stack myTop; // top of stack StackElement * myArray; // dynamic array to store elements }; // end of class declaration //====== FUNCTION DEFINITIONS ====== #include //--- Definition of Stack constructor template Stack::Stack(int numElements) { assert (numElements > 0); // check precondition myCapacity = numElements; // set stack capacity // allocate array with this capacity myArray = new(nothrow) StackElement[myCapacity]; if (myArray != 0) // memory available myTop = -1; else { cerr << "Inadequate memory to allocate stack \n" " -- terminating execution\n"; exit(1); } // or assert(myArray != 0); } //--- Definition of Stack copy constructor template Stack::Stack(const Stack & original) : myCapacity(original.myCapacity), myTop(original.myTop) { //--- Get new array for copy myArray = new(nothrow) StackElement[myCapacity]; if (myArray != 0) // check if memory available // copy original's array member into this new array for (int pos = 0; pos <= myTop; pos++) myArray[pos] = original.myArray[pos]; else { cerr << "*Inadequate memory to allocate stack ***\n"; exit(1); } } //--- Definition of Stack destructor template inline Stack::~Stack() { delete[] myArray; } //--- Definition of assignment operator template const Stack & Stack:: operator=(const Stack & rightHandSide) { if (this != &rightHandSide) // check that not st = st { //-- Allocate a new array if necessary if (myCapacity != rightHandSide.myCapacity) { delete[] myArray; // destroy previous array myCapacity = rightHandSide.myCapacity; // copy myCapacity myArray = new StackElement[myCapacity]; if (myArray == 0) // check if memory available { cerr << "*** Inadequate memory ***\n"; exit(1); } } myTop = rightHandSide.myTop; // copy myTop member for (int pos = 0; pos <= myTop; pos++) // copy stack elements myArray[pos] = rightHandSide.myArray[pos]; } return *this; } //--- Definition of empty() template inline bool Stack::empty() const { return (myTop == -1); } //--- Definition of push() template inline void Stack::push(const StackElement & value) { if (myTop < myCapacity - 1) //Preserve stack invariant { ++myTop; myArray[myTop] = value; } else { cerr << "*** Stack full -- can't add new value ***\n" "Must increase Stack's capacity\n"; exit(1); } } //--- Definition of display() template inline void Stack::display(ostream & out) const { for (int i = myTop; i >= 0; i--) out << myArray[i] << endl; } //--- Definition of operator<<() template inline ostream & operator<<(ostream & out, const Stack & st) { st.display(out); return out; } //--- Definition of top() template inline StackElement Stack::top() const { if ( !empty() ) return (myArray[myTop]); else { cerr << "*** Stack is empty -- returning garbage value ***\n"; StackElement garbage; return garbage; } } //--- Definition of pop() template inline void Stack::pop() { if (myTop >= 0) // Preserve stack invariant myTop--; else cerr << "*** Stack is empty -- can't remove a value ***\n"; } #endif