I'm in the process of learning how to create Stacks and linked lists. The program that I'm writing right now focuses on a template stack class. Everything was going smoothly when I made a stack of int, but my program started crashing when I started implementing a stack of char. To be specific it started messing up when I tried to implement a pop action on the stack of char.
Can you guys please verify that I'm doing this correctly and also let me know what I'm doing wrong with char stack?
Here's my code:
#include<iostream>
using namespace std;
#ifndef STACK_H
#define STACK_H
//STACK CLASS
template<typename T>
class Stack
{
public:
Stack(int = 10);
~Stack(){ delete stackPtr;};
bool isEmpty() const
{ return top == -1; }
bool isFull() const
{ return top == size - 1; }
//push and pop
bool push(const T&);
bool pop(T&);
private:
int size;
int top;
T *stackPtr;
};
//CONSTRUCTOR
template<typename T>
Stack<T>::Stack(int newSize)
: top(-1), size(newSize),
stackPtr(new T[size]) //allocate array using ptr ********
{
//empty constructor
};
//PUSH VALUES ONTO STACK
template<typename T>
bool Stack<T>::push(const T &pushVal)
{
if(!isFull())
{
stackPtr[++top] = pushVal;
return true;
}
return false;
};
//POP VALUES OFF OF STACK
template<typename T>
bool Stack<T>::pop(T &popVal)
{
if(!isEmpty())
{
popVal = stackPtr[top--];
return true;
}
return false;
};
#endif
//DRIVER
int main()
{
//STACK OF INT
Stack<int> intStack(5);
int intValue = 1;
cout << "Pushing values onto intStack: " << endl;
while(intStack.push(intValue))
{
cout << intValue << ' ';
intValue++;
}
cout << "\nStack is full, cannot push..."
<< endl << endl;
cout << "Popping values off of intStack: " << endl;
while(intStack.pop(intValue))
cout << intValue << ' ';
cout << "\nStack is empty, cannot pop..."
<< endl;
//STACK OF CHAR
Stack<char> charStack(5);
string greeting = "hello";
int strSize = greeting.length();
cout << "\nPushing values onto charStack: " << endl;
for(int i = 0; i < strSize; i++)
{
charStack.push(greeting.at(i));
cout << greeting.at(i) << ' ';
}
cout << endl;
cout << "Popping values off of charStack: " << endl;
for(int i = (strSize - 1); i >= 0; i++) //PROBLEM OCCURS
{
charStack.pop(greeting.at(i));
cout << greeting.at(i) << ' ';
}
system("pause");
}
for(int i = (strSize - 1); i >= 0; **i--**) //PROBLEM not anymore
{
charStack.pop(greeting.at(i));
cout << greeting.at(i) << ' ';
}
Probably it's not the source of your particular problem, but you really should use
delete[] stackPtr
instead of delete stackPtr in your destructor. Wikipedia explains why
Related
#include <iostream>
using namespace std;
class Stack {
private:
int size;
public:
Stack(int n)
{
size = n;
}
int stack_arr[size], top = -1;
void push(int a)
{
if (top >= 4)
cout << "Stack is full" << endl;
else {
top++;
stack_arr[top] = a;
}
}
void pop()
{
if (top <= -1)
cout << "There is no element remaining in stack" << endl;
else {
cout << "The popped element is " << stack_arr[top] << endl;
top--;
}
}
void peek()
{
if (top < 0) {
cout << "Stack is Empty";
}
else {
int x = stack_arr[top];
cout << "The last element in the Stack is: ";
cout << x << endl;
}
}
int isempty()
{
if (top == -1)
cout << "Stack is Empty: ";
else
return false;
}
void display()
{
if (top >= 0) {
cout << "Stack elements are:";
for (int i = top; i >= 0; i--)
cout << stack_arr[i] << " ";
cout << endl;
}
else
cout << "Stack is empty";
}
};
int main()
{
Stack s(5);
s.push(10);
s.push(12);
s.push(14);
s.push(10);
s.push(12);
s.push(14);
s.peek();
s.display();
s.pop();
s.display();
}
I'm facing the issue while compilation
13:9: error: invalid use of non-static data member 'Stack::size'
14:15: error: from this location
In member function 'void Stack::push(int)':
21:7: error: 'stack_arr' was not declared in this scope
In member function 'void Stack::pop()':
28:40: error: 'stack_arr' was not declared in this scope
In member function 'void Stack::peek()':
38:17: error: 'stack_arr' was not declared in this scope
In member function 'void Stack::display()':
53:13: error: 'stack_arr' was not declared in this scope
can anyone help me for giving idea how i can get stack size from constructor,if im doing wrong approach
I made your code compile, you had to do two simple modifications:
private:
int size;
int* stack_arr;
int top = 0;
public:
Stack(int n)
{
size = n;
stack_arr = new int[size];
}
You forgot to define top, also to achieve what you tried with a dynamic array you can use new. I also fixed some issues that lead to random dygits while printing, you basically were going out of array scope:
void push(int a) {
if (top == size - 1) // in your code it was top<=4,
//suppose it was only for your specific test case
// your forgot that it has to be generic
cout << "Stack is full" << endl;
else {
top++;
stack_arr[top] = a;
}
}
void pop() {
if (top == -1)
cout << "There is no element remaining in stack" << endl;
else {
cout << "The popped element is " << stack_arr[top] << endl;
top--;
}
}
void peek()
{
if (top == -1) {
cout << "Stack is Empty";
}
else {
int x = stack_arr[top];
cout << "The last element in the Stack is: ";
cout << x << endl;
}
}
int isempty() {
if (top == -1)
cout << "Stack is Empty: ";
else
return false;
}
void display() {
if (top > -1) {
cout << "Stack elements are:";
for (int i = top; i >= 0; i--)
cout << stack_arr[i] << " ";
cout << endl;
}
else
cout << "Stack is empty";
}
In modern c++ there is a rule: If you have anything in your class using new, you should make a destructor. And if you create a destructor, you should create copy constructor, and copy assignment operator (Its called rule of 3). For bonus, in this case, at least in my opinion, I also created move constructor and move assignment operator ( likely you wont use then in your case, that's why I say its bonus. It's known as rule of 5).
//Destructor
~Stack()
{
delete [] stack_arr;
}
//copy Constructor
Stack(const Stack& s)
:
size(s.size),
stack_arr(new int[size]),
top(s.top)
{
for (int i = 0; i <= top; i++) stack_arr[i] = static_cast<int>(s.stack_arr[i]);
}
//copy assignment operator
Stack& operator=(const Stack& s)
{
if (stack_arr != nullptr) delete[] stack_arr;
size = s.size;
top = s.top;
stack_arr = new int[size];
for (int i = 0; i <= top; i++) stack_arr[i] = static_cast<int>(s.stack_arr[i]);
return *this;
}
//move constructor
Stack(Stack&& s) noexcept :
top(std::move(s.top)),
size(std::move(s.size)),
stack_arr(std::move(s.stack_arr))
{
s.stack_arr = nullptr;
}
//move assignment operator
Stack& operator=(Stack&& s)noexcept
{
if (this != &s)
{
if (stack_arr != nullptr) delete[] stack_arr;
size = std::move(s.size);
top = std::move(s.top);
stack_arr = std::move(s.stack_arr);
}
return *this;
}
You can do what std::stack does, and delegate to an existing container type.
#include <iostream>
#include <vector>
class Stack {
private:
std::vector<int> data;
public:
Stack(std::size_t n) : data(n)
{
}
void push(int a)
{
try {
data.push_back(a);
} catch (std::bad_alloc) {
std::cout << "stack is full" << std::endl;
}
}
void pop()
{
if (data.empty()) {
std::cout << "There is no element remaining in stack" << std::endl;
} else {
std::cout << "The popped element is " << data.back() << std::endl;
data.pop_back();
}
}
void peek()
{
if (data.empty()) {
std::cout << "Stack is Empty" << std::endl;
} else {
std::cout << "The last element in the Stack is: " << data.back() << std::endl;
}
}
bool isempty()
{
return data.empty();
}
void display()
{
if (!data.empty()) {
std::cout << "Stack elements are:";
for (int i : data) {
std::cout << i << " ";
}
std::cout << endl;
} else {
std::cout << "Stack is empty" << endl;
}
}
};
main():
char inp[] = "(A+B)/(C*D))";
Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
Here is Infix constructor:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
Infix is inheriting from a class 'Stack':
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
When I run the code in main, it displays unusual output:
Element In Stack: (
Operator Array: /*-+%
In main: +%
Stack Object Destroyed!
But, when in main, if the comment the line declaring 'Infix' object declaration, the code runs fine:
In main: (A+B)/(C*D))
EDITS:
Stack Class
#include<iostream>
using namespace std;
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
bool Stack:: push(char elementToPush) {
if(top > 98) {
cout << "\nStack Overflow!!";
return false;
} else {
arr[++top] = elementToPush;
return true;
}
}
char Stack:: pop() {
if(top <= -1) {
cout << "\nStack Underflow!!";
return ' ';
} else {
return (arr[top--]);
}
}
char Stack:: peek() {
if(top > 98) {
cout << "\nStack Overflow!!";
return ' ';
} else {
return arr[top];
}
}
bool Stack:: isEmpty() {
return (top <= 0);
}
void Stack:: displayAll() {
if(top <= -1) {
cout << "null";
return;
}
int i = top;
while (i >= 0) {
cout << arr[i] << " ";
--i;
}
cout << "\n";
}
Infix Class
#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>
using namespace std;
class Infix : public Stack {
string outputString;
char operatorArray[];
public:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
string infixToPostfix(char *, int);
bool manupulateOperator(char, int);
int checkPrecedence(char);
~Infix() {
cout << "\nStack Object Destroyed!" << endl;
}
};
string Infix:: infixToPostfix(char *str, int size) {
cout << "\nGiven String: " << str << endl;
int x;
for(int i = 0; i < size; ++size) {
x = str[i];
if(x != ' ') {
if(x == ')') {
while(returnTop() != '(') {
cout << pop() << " popped!\n";
}
cout << pop() << " popped!\n";
} else if(isalpha(x)) {
cout << x;
} /* else{ // scanned character is an operator
if(manupulateOperator(x, i)) {
} else {
return " ";
}
} */
}
}
return outputString;
}
bool Infix::manupulateOperator(char c, int position) {
try {
char topElement = *returnElement(returnTop());
if(checkPrecedence(c) == -1) {
cout << "\nErr\n";
}else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
push(c);
cout << c << " pushed!\n";
}
} catch(std::exception e) {
std::cerr << e.what() << '\n';
return false;
} catch (char* Ce) {
cout << Ce << endl;
}
return true;
}
int Infix::checkPrecedence(char c) {
/*
+ -> 1
- -> 1
* -> 2
/ -> 2
% -> 2
*/
switch(c) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '%':
return 2;
default:
// throw "Illegal Operator Detected!";
cout << "Illegal Operator Detected: " << c << endl;
return -1;
}
}
int main() {
cout << endl;
int x = 1;
char inp[] = "(A+B)/(C*D))";
//Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
// cout << i.infixToPostfix(input + ')', sizeof(input));
/* for(int i = 0; i < strlen(inp); ++i) {
cout << inp[i];
}
*/
return 0;
}
You are declaring operatorArray as an array of char but you are not assigning any memory for it! So, when you then call strcpy(operatorArray, "/*-+%"); in your Infix constructor, you are causing undefined behaviour by attempting to copy the given string constant to memory that hasn't been assigned - and this appears to be overwriting the inp[] array declared in your main.
To fix this, I would suggest giving your operatorArray member a specific size, which will be large enough to accommodate whatever string you want to copy to it - 8 characters will work in the sample code you've given:
class Infix : public Stack {
string outputString;
char operatorArray[8]; // Make this member a REAL array of characters.
//..
Your variable char operatorArray[] have no memory allocated when your constructor is called. When you use strcpy, you write to a place where you don't have permissions in your memory, and therefore on other informations.
To find these kinds of mistakes, I recommend using valgrind.
char operatorArray[]; is not allowed in Standard C++.
If you didn't see an error message then I would recommend adjusting compiler settings to follow the standard form of the language, this would have saved you a lot of time.
I wrote a encoding program using the C++ stack library. Now I am trying to implement my own stack class, however I notice there are size() and top() member functions in the stack library. I am not sure how to implement my code without these functions, or how to write those functions in my class to get them to work properly with the code I already have.
Here is the areas that the stack library functions are being called in my readFileEncode(string filename, stack<char> &text, string cypher) function:
ifstream file(fileName, ios::in | ios::binary);
stack<char> temp;
char ch;
while (file.get(ch)){
temp.push(ch ^ cypher[temp.size() % cypher.length()]);
}
while (!temp.isEmpty()){
text.push(temp.top());
temp.pop();
}
Here is my stack class:
#include<iostream>
#define TRUE 1
#define FALSE 0
template <class TYPE>
class stack{
struct node{
TYPE element;
node *next;
};
public:
node *top;
int stackSize;
stack(void); //constructor
~stack(void); //destructor free the stack
void push(TYPE & value);
TYPE pop(void);
TYPE peek(void);
int isEmpty(void); //returns TRUE if empty
void print(void);
void reset(void); //pop all the elements off the stack
size_t size(void) const;
TYPE topOf(void) const;
};
template <class TYPE>
stack<TYPE>::stack(void){
top = NULL;
stackSize = 0;
}
template <class TYPE>
stack<TYPE>::~stack(void){
cout << "Entering Stack Destructor" << endl;
reset();
cout << "Exiting Stack Destructor" << endl;
}
template <class TYPE>
void stack<TYPE>::push(TYPE & value){
node *temp = new node;
if (temp == NULL){
cout << "Push: Memory Allocation Error" << endl;
exit(1);
}
temp->element = value;
temp->next = top;
top = temp;
stackSize++;
}
template <class TYPE>
TYPE stack<TYPE>::pop(void){
TYPE returnElement;
if (top != NULL){
node *temp = top;
returnElement = top->element;
top = top->next;
delete temp; //delete the node
stackSize--;
}
return(returnElement);
}
template <class TYPE>
TYPE stack<TYPE>::peek(void){
TYPE returnElement;
if (top != NULL)
returnElement = top->element;
cout << "Peek: " << returnElement << endl;
return(returnElement);
}
template <class TYPE>
int stack<TYPE>::isEmpty(void){
if (stackSize == 0)
return(TRUE);
else
return(FALSE);
}
template <class TYPE>
void stack<TYPE>::reset(void){
cout << "Reset Stack" << endl;
while (isEmpty() != TRUE){
pop();
}
}
template <class TYPE>
void stack<TYPE>::print(void){
cout << "Inside Print Stack" << endl;
cout << "Stack size = " << stackSize << endl;
node * temp = top;
while (temp != NULL){
cout << " " << temp->element << endl;
temp = temp->next;
}
}
template <class TYPE>
size_t size(void) const{
return stackSize;
}
template <class TYPE>
TYPE stack<TYPE>::topOf(void) const{
return (*top).element;
}
This stack class is based on what I know of stack's. If there is anything wrong, it is because this is the first time I have written a stack class.
So basically, I am having problems either 1) writing the size() and top() functions, or 2) rewriting the while loops in my readFileEncode() function to use what I have. I had help properly writing the code to work with the stack library, but now trying to implement my own class is causing me problems. Any help would be appreciated.
EDIT 1: With the help of dyp, I changed the variable name of int size to int stackSize everywhere it appears in the class. Also, I change the function top() to topOf()
EDIT 2: Changed void push(TYPE &value) to void push(TYPE const& value) in all instances. Code is updated above. I used the following main() to test the class:
#include <iostream>
#include <cstdlib>
#include "stack.h"
using namespace std;
int main()
{
stack<int> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
cout << "size: " << s.size() << endl;
cout << "top element: " << s.topOf() << endl;
s.pop();
s.pop();
cout << "size: " << s.size() << endl;
cout << "top element: " << s.topOf() << endl;
cout << "empty: " << s.isEmpty() << endl;
s.pop();
s.pop();
s.pop();
cout << "size: " << s.size() << endl;
//cout << "top element: " << s.top() << endl;
cout << "empty: " << s.isEmpty() << endl;
system ("pause");
}
Everything worked fine, however when I attached the stack.h file to my encoding program, I get the following errors:
At file.put(text.top()); I get "term does not evaluate to a function taking 0 arguments," and the same error at text.push(temp.top());. I get the error, but not exactly sure how to fix it.
I also had to move public: in my class above node *top; int stackSize; because I got errors about them being private. This was not a problem with my test program. Not sure if that is ok either.
I used the following code to test my stack:
int main()
{
stack<int> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
cout << "size: " << s.size() << endl;
cout << "top element: " << s.topOf() << endl;
s.pop();
s.pop();
cout << "size: " << s.size() << endl;
cout << "top element: " << s.topOf() << endl;
cout << "empty: " << s.isEmpty() << endl;
s.pop();
s.pop();
s.pop();
cout << "size: " << s.size() << endl;
//cout << "top element: " << s.top() << endl;
cout << "empty: " << s.isEmpty() << endl;
system ("pause");
}
I changed the code in my following stack class to the following and it seems to have worked:
void push(TYPE const& value);
size_t size(void) const;
TYPE topOf(void) const;
and:
void stack<TYPE>::push(TYPE const& value){
node *temp = new node;
if (temp == NULL){
cout << "Push: Memory Allocation Error" << endl;
exit(1);
}
temp->element = value;
temp->next = top;
top = temp;
stackSize++;
}
template <class TYPE>
size_t stack<TYPE>::size(void) const{
return stackSize;
}
template <class TYPE>
TYPE stack<TYPE>::topOf(void) const{
return (*top).element;
}
Also changed all occurrences of top() in my main to topOf(). Not sure if this is all proper, but it works, and I will take dyp's advice and turn it in at CodeReview.
everything i have read says this should be easy and that you just add these three lines
typedef double* DoublePtr;
DoublePtr p;
p = new double [10]
but where do i add this code? Everything i have tried just breaks my program what am I missing? I tried a set function to set the value of max size but it didn't work either
does anyone know how to do this?
#include<iostream>
using namespace std;
const int MAX_SIZE = 50;
class ListDynamic
{
public:
ListDynamic();
bool full();
int getSize();
void addValue(double value);
double getValue(int index);
double getLast();
void deleteLast();
friend ostream& operator <<(ostream& out, const ListDynamic& thisList);
private:
double listValues[MAX_SIZE];
int size;
};
int main()
{
double value;
ListDynamic l;
cout << "size of List " << l.getSize() << endl;
cout << "New size of List " << l.getSize() << endl;
cout << "First Value: " << l.getValue(0) << endl;
cout << "Last Value: " << l.getLast() << endl;
cout << "deleting last value from list" << endl;
l.deleteLast();
cout << "new list size " << l.getSize() << endl;
cout << "the list now contains: " << endl << l << endl;
system("pause");
return 0;
}
ListDynamic::ListDynamic()
{
size = 0;
}
bool ListDynamic::full()
{
return (size == MAX_SIZE);
}
int ListDynamic::getSize()
{
return size;
}
void ListDynamic::addValue(double value)
{
if (size < MAX_SIZE)
{
listValues[size] = value;
size++;
}
else
cout << "\n\n*** Error in ListDynamic Class: Attempting to add value past max limit.";
}
double ListDynamic::getValue(int index)
{
if (index < size)
return listValues[index];
else
cout << "\n\n*** Error in ListDynamic Class: Attempting to retrieve value past current size.";
}
double ListDynamic::getLast()
{
if (size > 0)
return getValue(size - 1);
else
cout << "\n\n*** Error in ListDynamic Class: Call to getLast in Empty List.";
}
void ListDynamic::deleteLast()
{
if (size > 0)
size--;
else
cout << "\n\n*** Error in ListDynamic Class: Call to deleteLast in Empty List.";
}
ostream& operator <<(ostream& out, const ListDynamic& thisList)
{
for (int i = 0; i < thisList.size; i++)
out << thisList.listValues[i] << endl;
return out;
}
You need to change listValues to a double*
double* listValues;
And when you add a value greater than the size, you'll need to reallocate the array your array and copy the elements of the former array to the new one. For example:
void ListDynamic::addValue(double value)
{
if (full())
{
double* temp = new double[size];
std::copy(listValues, listValues + size, temp);
delete[] listValues;
listValues = new double[size + 1];
std::copy(temp, temp + size, listValues);
listValues[size] = value;
delete[] temp;
} else
{
listValues[size++] = value;
}
}
I created an array for studentrecords and am supposed to pop it into my stack.. well everything works except for my stack.pops and stack.pushes in MAIN...I am so close to finishing this program I am wondering if anyone knows any solutions?
#include <iostream>
#include <list>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <string>
using namespace std;
class Studentrecords
{
private:
struct student
{
string name;
string address;
int ID;
double gpa;
};
student *stackArray;
int stackSize;
int top;
public:
Studentrecords();
Studentrecords(int size);
~Studentrecords();
void push(string name, string address, int id, double gpa);
void pop();
bool isFull() const;
bool isEmpty() const;
void display();
};
Studentrecords::Studentrecords(int size)
{
stackArray = new student[size];
top = -1;
}
Studentrecords::Studentrecords()
{
stackSize = 20;
stackArray = new student[stackSize];
top = -1;
}
Studentrecords::~Studentrecords()
{
delete [] stackArray;
}
void Studentrecords::push (string name, string address, int id, double gpa)
{
if (isFull())
{
cout << "The stack is full!" << endl;
}
else
{
student newStudent;
newStudent.name = name;
newStudent.address= address;
newStudent.ID = id;
newStudent.gpa = gpa;
stackArray[top] = newStudent;
top++;
}
}
void Studentrecords::pop ()
{
if (isEmpty())
{
cout << "The stack is empty!" << endl;
}
else
{
cout << stackArray[top-1].name << endl;
cout << stackArray[top-1].address << endl;
cout << stackArray[top-1].ID << endl;
cout << stackArray[top-1].gpa << endl;
top--;
}
}
bool Studentrecords::isFull() const
{
bool status;
if (top == stackSize - 1)
status = true;
else
status = false;
return status;
}
bool Studentrecords::isEmpty() const
{
bool status;
if (top == -1)
status = true;
else
status = false;
return status;
}
void Studentrecords::display()
{
for (int i = 0; i< top; i++)
{
cout << stackArray[i].name << endl;
cout << stackArray[i].address << endl;
cout << stackArray[i].ID << endl;
cout << stackArray[i].gpa << endl << endl;
}
}
int main()
{
int catchVar;
Studentrecords stack();
cout << "Pushing 1st";
stack.push("Jonny", "123 ave", 2343, 3.2);
cout << "pushing 2nd";
stack.push("Robby", "123 ave", 2343, 3.2);
cout << "Popping ";
stack.pop(catchVar);
cout << catchVar << endl;
cout << "Popping ";
stack.pop(catchVar);
cout << catchVar << endl;
return 0;
}
Studentrecords stack();
Does not declare a Studentrecords named stack, it declares a function named stack that returns a Studentrecords. Change it to
Studentrecords stack;
Also your class needs at least a copy constructor and assignment operator.
Can you post the compiler's error?
Or the produced output VS the expected output?
Without that, I'll have to say that your pop function doesn't take arguments and you are passing it catchVar... that would be a compiler error.