I have a Data Structures assignment to use stacks for postfix algorithm. I think I'm nearly there but am struggling on a couple of things.
What do I put into the postfixstack.pop() arguments on Line 83 of cpp file?
How do I check if the stack is empty on Line 87 of cpp file?
I have 2 files, a .cpp and a .h file, both of them are below.
Thanks for any help.
using namespace std;
#include <iostream>
#include <stdlib.h>
#include <string>
#include "stack.h"
//Purpose of the program: **
//Algorithm: **
int main()
{
stack postfixstack; // integer stack
string expression; // user entered expression
cout << "type a postfix expression: " ;
cin >> expression;
int i = 0; // character position within expression
char item; // one char out of the expression
int box1; // receive things from pop
int box2; // receive things from pop
while (expression[i] != '\0')
{
try
{
item = expression[i]; // current char
// ** do all the steps in the algorithm given in Notes-1
if (item >= '0' && item <= '9') {
postfixstack.push(item);
}
else if (item == '+' || item == '-' || item == '*') {
if (item == '+') {
postfixstack.pop(box1);
postfixstack.pop(box2);
int tempResult = (box1 + box2);
postfixstack.push(tempResult);
}
if (item == '-') {
postfixstack.pop(box1);
postfixstack.pop(box2);
int tempResult = (box1 - box2);
postfixstack.push(tempResult);
}
if (item == '*') {
postfixstack.pop(box1);
postfixstack.pop(box2);
int tempResult = (box1 * box2);
postfixstack.push(tempResult);
}
}
else {
throw ;
}
} // this closes try
// Catch exceptions and report problems and quit the program now (exit(1)).
// Error messages describe what is wrong with the expression.
catch (stack::Overflow) {
{cerr << "Error: You have caused the stack to overflow." << endl; }
exit(1);
}
catch (stack::Underflow)
{cerr << "Error: You have caused the stack to underflow." << endl;
exit(1);
}
catch (char const* errormsg ) // for invalid item case
{cerr << "Error: You have entered an invalid item." << endl;
exit(1);
}
i++; // go back to the loop after incrementing i
}// end of while
// After the loop successfully completes:
// Pop the result and show it.
*postfixstack.pop();*
// If anything is left on the stack, an incomplete expression
// was found so inform the user.
if (*Need to check if stack is empty*) {
cerr << "Elements remain on the stack, incomplete expression error" << endl;
exit(1);
}
}// end of the program
****This is the beginning of the header file*****
// File type: header file stack.h
//=======================================================
//----- Globally setting up the aliases ----------------
const int MAX = 10; // The MAX number of elements for the stack
// MAX is unknown to the client
typedef int el_t; // the el_t type is char for now
// el_t is unknown to the client
//-------------------------------------------------------
class stack
{
private: // to be hidden from the client
el_t el[MAX]; // el is an array of el_t's
int top; // top is index to the top of stack
public: // available to the client
// Add exception handling classes here
class Overflow {}; // empty class – used as an exception name only
class Underflow {}; // empty class – used as an exception name only
// prototypes to be used by the client
// Note that no parameter variables are given
stack(); // constructor to create an object
~stack(); // destructor to destroy an object
// PURPOSE: if not full, enters an element at the top;
// otherwise throws an exception - Overflow
// PARAMETER: pass the element to be pushed
void push(el_t);
// PURPOSE: if not empty, removes and gives back the top element;
// otherwise throws an exception - Underflow
// PARAMETER: provide variable to receive the popped element (by ref)
void pop(el_t&);
// PURPOSE: if not empty, gives the top element without removing it;
// otherwise, throws an exception - Underflow
// PARAMETER: provide the top element of the stack (pass by reference)
void topElem(el_t&);
//PURPOSE: Determines if the stack is Empty. Returns true if stack is empty
bool isEmpty();
//PURPOSE: Determines if the stack is Full. Returns true if stack is full
bool isFull();
//PURPOSE: Displays all of the elements of the stack
void displayAll();
//PURPOSE: Clears all of the elements in the stack until it is empty
void clearIt();
};
The way you are implementing the stack as an array you can use the index (your top variable) to keep track of your stack's size as long as its use is well defined.
For instance, you can say that top is pointing to the next available place to put a new element so that an empty stack would have top == 0. This would solve the part for checking if an array is empty.
Following that same definition when you pop the stack you're removing the top element. If the datatype your stack is holding is a simple type you can just decrease the value of top by one.
void pop (el_t& val) //Perhaps return the value instead of return by reference
{
val= el[--top]; //Decrease top first because top is pointing to next EMPTY space.
}
Related
I am working on a class assignment, relatively new to the c++ language and I have tried to function the code to hopefully get rid of the error but, have not been successful. can anyone help me out?, I am primarily working with mathstack template class and calling it to push a number to the stack but the following code comes up.
error message : clang++-7 -pthread -std=c++17 -o main MathStack.cpp main.cpp
/tmp/main-69d6a9.o: in function 'menu(int&)'; main.cpp:(.text+0x297): undefined reference to
'MathStack<int>::push(int)'clang: error : linker command failed with code 1 (use -v to see
invocation)
**/ Implementation file for the MathStack class**
#include "MathStack.h"
#include <iostream>
//***********************************************
// Member function add. add pops *
// the first two values off the stack and *
// adds them. The sum is pushed onto the stack. *
//***********************************************
template <class T>
void MathStack<T>::add()
{
T num, sum;
// Pop the first two values off the stack.
pop(sum);
pop(num);
// Add the two values, store in sum.
sum += num;
// Push sum back onto the stack.
push(sum);
}
//***********************************************
// Member function sub. sub pops the *
// first two values off the stack. The *
// second value is subtracted from the *
// first value. The difference is pushed *
// onto the stack. *
//***********************************************
template <class T>
void MathStack<T>::sub()
{
T num, diff;
// Pop the first two values off the stack.
pop(diff);
pop(num);
// Subtract num from diff.
diff -= num;
// Push diff back onto the stack.
push(diff);
}
//**********************************************
// Member function mult. multiplies first two *
// values of the stack. *
//**********************************************
template <class T>
void MathStack<T>::mult()
{
T num, res;
// pop the first two values of the stack
pop(res);
pop(num);
// multiply thw two values
res = res*num;
// push result back into the stack
push(res);
}
template <class T>
//*********************************************
// Member funciton div. divides the first two *
// values of the stack. *
// shows an error when divided by zero *
//*********************************************
void MathStack<T>::div()
{
T quot, divisor;
// pop the first two values of the stack
pop(divisor);
pop(quot);
// exexption
if (divisor == 0)
{
cout << "ERROR: Cannot divide by zero.\n";
}
else {quot = quot/divisor; } // division formula
// push quotient back into the stack
push(quot);
}
//*************************************************
// Member function push pushes the argument onto *
// the stack. *
//*************************************************
template <class T>
void MathStack<T>::push(T num)
{
if (isFull())
{
cout << "The stack is full.\n";
}
else
{
top++;
stackArray[top] = num;
}
}
//****************************************************
// Member function pop pops the value at the top *
// of the stack off, and copies it into the variable *
// passed as an argument. *
//****************************************************
template <class T>
void MathStack<T>::pop(T &num)
{
if (isEmpty())
{
cout << "The stack is empty.\n";
}
else
{
num = stackArray[top];
top--;
}
}
//***************************************************
// Member function isFull returns true if the stack *
// is full, or false otherwise. *
//***************************************************
template <class T>
bool MathStack<T>::isFull() const
{
bool status;
if (top == stackSize - 1)
status = true;
else
status = false;
return status;
}
//****************************************************
// Member funciton isEmpty returns true if the stack *
// is empty, or false otherwise. *
//****************************************************
template <class T>
bool MathStack<T>::isEmpty() const
{
bool status;
if (top == -1)
status = true;
else
status = false;
return status;
}
// file specifies the stack class and use of math functions
#include <iostream>
#include "MathStack.h"
using namespace std;
// Constants for the menu choices
const int Add = 1,
Subtract = 2,
Multiply = 3,
Division = 4,
QUIT = 5;
// Function prototypes
void menu(int &);
void getStackSize(int &);
int main()
{
int stackSize; // The stack size
int choice; // To hold a menu choice
menu(choice);
// Create the stack.
MathStack<int> Math(stackSize);
MathStack<float> Math1(stackSize);
return 0;
}
//************************************************
// The menu function displays the menu and gets *
// the user's choice, which is assigned to the *
// reference parameter. *
//************************************************
void menu(int &choice)
{
int stackSize;
int number;
getStackSize(stackSize);
// Display the menu and get the user's choice.
cout << "\nWhat do you want to do?\n"
<< Add
<< " - Add items from the stack\n"
<< Subtract
<< " - Subtact items from the stack\n"
<< Multiply
<< " - Multiply items from the stack\n"
<< Division
<< " - Divide items form the stack\n"
<< QUIT
<< " - Quit the program\n"
<< "Enter your choice: ";
cin >> choice;
// Validate the choice
while (choice < Add || choice > QUIT)
{
cout << "Enter a valid choice: ";
cin >> choice;
}
switch(choice)
{
case 1:
MathStack<int> Math(stackSize);
for (int i = 0; i < stackSize; i++)
{
cout << " Enter number to insert to the stack:\n" << endl;
}
cin >> number;
Math.push(number);
}
}
//************************************************
// The getStackSize function gets the desired *
// stack size, which is assigned to the *
// reference parameter. *
//************************************************
void getStackSize(int &size)
{
// Get the desired stack size.
cout << "How big should I make the stack? ";
cin >> size;
// Validate the size.
while (size < 1)
{
cout << "Enter 1 or greater: ";
cin >> size;
}
}
i was studying template classes andi have seen a tutorial code in a book.
There is a class named Stack as the following:
// Stack class template.
#ifndef STACK_H
#define STACK_H
template< typename T >
class Stack
{
public:
Stack( int = 10 ); // default constructor (stack size 10)
// destructor
~Stack()
{
delete [] stackPtr; // deallocate internal space for stack
} // end ~Stack destructor
bool push( const T& ); // push an element onto the stack
bool pop( T& ); // pop an element off the stack
// determine whether Stack is empty
bool isEmpty() const
{
return top == -1;
} // end function isEmpty
// determine whether Stack is full
bool isFull() const
{
return top == size - 1;
} // end function isFull
private:
int size; // # of elements in the stack
int top; // location of the top element (-1 means empty)
T *stackPtr; // pointer to internal representation of the stack
}; // end class template Stack
// constructor template
template< class T >
Stack< T >::Stack( int s )
: size( s > 0 ? s : 10 ), // validate size
top( -1 ), // Stack initially empty
stackPtr( new T[ size ] ) // allocate memory for elements
{
// empty body
} // end Stack constructor template
// push element onto stack;
// if successful, return true; otherwise, return false
template< class T >
bool Stack< T >::push( const T &pushValue )
{
if ( !isFull() )
{
stackPtr[ ++top ] = pushValue; // place item on Stack
return true; // push successful
} // end if
return false; // push unsuccessful
} // end function template push
// pop element off stack;
// if successful, return true; otherwise, return false
template< class T >
bool Stack< T >::pop( T &popValue )
{
if ( !isEmpty() )
{
popValue = stackPtr[ top-- ]; // remove item from Stack
return true; // pop successful
} // end if
return false; // pop unsuccessful
} // end function template pop
#endif
Also there is a main tester function that uses a function template as following.
// Fig. 14.4: fig14_04.cpp
// Stack class template test program. Function main uses a
// function template to manipulate objects of type Stack< T >.
#include <iostream>
#include <string>
#include "Stack.h" // Stack class template definition
using namespace std;
// function template to manipulate Stack< T >
template< typename T >
void testStack(
Stack< T > &theStack, // reference to Stack< T >
T value, // initial value to push
T increment, // increment for subsequent values
const string stackName ) // name of the Stack< T > object
{
cout << "\nPushing elements onto " << stackName << '\n';
// push element onto Stack
while ( theStack.push( value ) )
{
cout << value << ' ';
value += increment;
} // end while
cout << "\nStack is full. Cannot push " << value
<< "\n\nPopping elements from " << stackName << '\n';
// pop elements from Stack
while ( theStack.pop( value ) )
cout << value << ' ';
cout << "\nStack is empty. Cannot pop" << endl;
} // end function template testStack
int main()
{
Stack< double > doubleStack( 5 ); // size 5
Stack< int > intStack; // default size 10
testStack( doubleStack, 1.1, 1.1, "doubleStack" );
testStack( intStack, 1, 1, "intStack" );
system("pause");
} // end main
What could be reason usage of reference in testStack function?
When i make change denition as
Stack< T > theStack,
i get an error message that says "debug assertion failed" after program ends.
There is no copy constructor in Stack, so when you replace
Stack<T>&
to
Stack<T>
the default ctor is used.
The second copy is destroying already cleaned pointer.
delete[] stackPtr;
i think the best think is using reference when using a class's instance as a function parameter. But i just wanted to try copy constructor and added following code into Stack class and nothing changed. Error message appeared again with program end. What could be the correct copy constructor function?
// copy constructor template
template< typename T >
Stack< T >::Stack(const Stack &something)
{
top = something.top;
size = something.size;
stackPtr = something.stackPtr;
}
So I have a stack created as below. The variable top is supposed to represent the current index, or the "top index". So by doing some testing, the constructor does get called and the value of top is -1 while the program is still running the constructor method. However, after creating the stack object, and testing to see what the value of top is, I keep getting top to be 32767. Literally, all that main does is create a new stack as
Stack s; //Testing while this is running to see value of top... I get -1
//Testing here to see value of top... I get 32767
-
The stack is created as shown below.
#ifndef __STACK_H_
#define __STACK_H_
class Stack{
int stackSize;
int top;
char* items;
public:
Stack();
~Stack();
void push(char c);
char pop();
bool isFull();
bool isEmpty();
};
#endif
And the implementation as below:
/* STACK IMPLEMENTATION FILE */
#include "stack.h"
#include <iostream>
using namespace std;
Stack::Stack(){
cout << "Ctor is run." << endl;
stackSize = 10; //Stack Size is 10
int top = -1; //Currently empty stack
cout << top << endl;
items = new char[stackSize];
}
Stack::~Stack(){ //Destructor
delete[] items;
}
void Stack::push(char c){ //Push next into stack
items[++top] = c;
cout << top << endl;
}
char Stack::pop(){ //Pop one from stack
return items[top--];
}
bool Stack::isFull(){ //Checks to see if stack is full
if (top + 1 == stackSize) return true;
}
bool Stack::isEmpty(){ //Checks to see if stack is empty
if (top == -1) return true;
}
You want top = 1 not int top = 1 in your constructor. The former assigns to the member, the latter initialises a local variable that goes out of scope at the end of the constructor.
So I'm trying to learn about Templates and the Fifo and Lifo stack stuff. I've been playing around with some code that deals with this, and I can get the int data to do what I want for testing but I can't for the life of me figure out how to get this to work with a string.
The way I have the code keeps crashing on me, but doesn't give me any errors, so I thought I'd pop in here and see if anybody could tell me what I'm doing wrong. Here's my code:
-----------//my header//---------------------
#include <stdlib.h>
#include <iostream>
#include <string>
#ifndef STACK_H_
#define STACK_H_
template<class T>
class StackTest
{
private:
unsigned int maxSize;
T *stackData;
int top;
public:
StackTest(int size){
stackData = new T[size];//to hold the T type data items
top = -1;//no items on the stack
maxSize = size;//set maximum size that stack can hold
}
virtual ~StackTest(){}
int count(){
return top + 1;
}
bool isEmpty(){
return top == -1 ? true : false;
}
bool isFull(){
return top == maxSize - 1 ? true : false;
}
T* peek(){
if(!isEmpty())//check for empty
return &stackData[top - 1];
}
T* pop(){
if(!isEmpty()){
top -= 1;//decrease the top by 1 to indicate the delete
return &stackData[top];//return deleted item
}
return NULL;
}
void push(T* item){
stackData[top++] = *item;//insert to data array and increase the top by one
}
};
#endif /* STACK_H_ */
-----------//my main//---------------
#include <iostream>
#include <string>
#include "Pair.h"
using namespace std;
int main() {
int dataTest;
string strTest;
StackTest<int> intStack(10);
StackTest<string> stringStack(50);
//Insert data into the stack
dataTest = 3;
intStack.push(&dataTest);
dataTest = 4;
intStack.push(&dataTest);
dataTest = 5;
intStack.push(&dataTest);
dataTest = 6;
intStack.push(&dataTest);
strTest = "test";
stringStack.push(&strTest);
//Show the top item
cout << *intStack.peek() << endl;
cout << *stringStack.peek() << endl;
//Pull the top item out (twice)
intStack.pop();
intStack.pop();
//Show the new top item
cout << *intStack.peek() << endl;
return 0;
}
So if anyone feels like giving me some pointers I would really appreciate it, thanks.
There are a few issues with your implementation. One of the most subtle is in the push() member function:
void push(T* item){
stackData[top++] = *item; //insert to data array and increase the top by one
// ^^
// You want pre-increment here!
}
This is incrementing top and using the old value as an index into stackData. Since top is -1 when the stack is empty, your program is actually doing:
stackData[-1] = *item;
top = 0;
Needless to say that the first assignment results in undefined behavior.
Another source of undefined behavior is the peek() member function, which does not return anything when the stack is empty:
T* peek(){
if(!isEmpty())//check for empty
return &stackData[top - 1];
}
Per paragraph 6.6.3/2 of the C++11 Standard:
[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
But that's not the only issue: the other problem is with the access of stackData:
return &stackData[top - 1];
When top is not equal to or greater than one, this will also result in undefined behavior, since you would be taking the address of a (non-)object located at a negative address in the array.
Also, I suggest to rewrite isEmpty() and isFull() as follows:
bool isEmpty(){
return (top == -1);
}
bool isFull(){
return (top == maxSize - 1);
}
As a general advice, consider not using the value -1 for top when the stack is empty. As Ben Voigt mentions in the comments, this is leading you to a lot of off-by-one errors.
Also, as pointed out by DyP, your destructor is not freeing the memory allocated in the constructor, so your StackTest object is leaking memory. And after doing that, since we're at it, you may want to have a look at the so-called Rule of Three, that your program would be violating.
I am a little stuck on how to use the stack and why I would even use stack in the code I am writing. The assingment says to write a program that checks if the user input is well-Iformed or not. It is a simple prgram that has three different selections the use can choose from. 1. basic brackets () 2. standard brackets ()[]{} and 3. User-definded brackets. The only thing the main program is suppose to do is to check if the users input is well-formed or not and display only that message on the screen.
I have a StackLS.cpp and a Stack.h file I am using along with my main.cpp. I will paste a sample code below from each.
StackLS.h
typedef int elemType; // flexible data type
class StackLS
{
private:
// inner class node
class Node
{
public:
elemType data; // data portion
Node *next; // link to the seccessor
}; // end Node
// data members
Node *topItem; // pointer to the top element of this stack
// utilities
public:
// constructors
StackLS(void); // default constructor
StackLS(const StackLS& aStack); // copy constructor
// observers
bool isEmpty(void) const;
// returns true if this stack is empty
// false otherwise
bool isFull(void) const;
// returns true if this stack is full
// false otherwise
elemType top(void) const;
// precondition: this stack is not empty
// returns top element in this stack
// transformers
void push(const elemType& item);
// precondition: this stack is not full
// adds item to this stack
void pop(void);
// removes top element from this stack if exist
// remains empty otherwise
void makeEmpty(void);
// makes this stack empty
// destructor
~StackLS(void);
}; // end StackLS
StackLS.cpp
// constructors
StackLS::StackLS(void)
// default constructor
{
topItem = 0;
} // end default constructor
StackLS::StackLS(const StackLS& aStack)
// copy constructor
{
} // end copy constructor
// observers
bool StackLS::isEmpty(void) const
// returns true if this stack is empty
// false otherwise
{
return topItem == 0;
} // end isEmpty
bool StackLS::isFull(void) const
// returns true if this stack is full
// false otherwise
{
return false;
} // end isFull
elemType StackLS::top(void) const
// precondition: this stack is not empty
// returns top element in this stack
{
// return (*topItem).data;
return topItem->data;
} // end top
// transformers
void StackLS::push(const elemType& item)
// precondition: this stack is not full
// adds item to this stack
{
Node *newNode = new Node;
newNode->data = item;
newNode->next = topItem;
topItem = newNode;
} // end push
void StackLS::pop(void)
// removes top element from this stack if exist
// remains empty otherwise
{
if (topItem != 0)
{
Node *temp = topItem;
topItem = topItem->next;
delete temp;
}
} // end pop
void StackLS::makeEmpty(void)
// makes this stack empty
{
while (topItem != 0)
{
Node *temp = topItem;
topItem = topItem->next;
delete temp;
}
} // end makeEmpty
// destructor
StackLS::~StackLS(void)
{
//while (!isEmpty())
// pop();
while (topItem != 0)
{
Node *temp = topItem;
topItem = topItem->next;
delete temp;
}
} // end destructor
Here is the main.cpp that I have so far.
main.cpp
#include <iostream>
#include <string>
#include "StackLS.h"
using namespace std;
do {
int main()
{
char answer;
char n;
StackLS stack;
cout << " ********** MENU ********** " << endl;
cout << " 1. Basic Brackets () " << endl;
cout << " 2. Standard Brackets ()[]{} " << endl;
cout << " 3. User-Defined brackets " << endl;
cout << " Please enter your choice: " << endl;
switch (choice){
case 1:
cout << "Current Setting: () " << endl;
cout << "Enter your expression followed by a ; : " << endl;
do {
cin >> answer;
while (answer != ;)
}
} // end main
}
while (choice != 'n' || 'N')
Again I am wondering how I would use the stack I have shown you in this program (main.cpp). I am a little confused on why I would use stack and why. Any help is appreciated. Thanks. The main.cpp may not be right but again I am learning and that is why I am here to learn more. Thanks
When you see an opening brace, you push it onto the stack. When you see a closing brace, you make sure it is the counterpart of the brace on top of the stack, then pop it off. When your input is done, you make sure the stack is empty.