Stack Iterator in C++ - c++

I want to understand what iterators are, how they are made. So int this code iterators are created for Stack.My question are
how we can write Stack s2(s1), if we don't have class named Stack which has explicit constructor, insted we have StackIter class , which has explicit constructor ?
What does this mean: StackIter *Stack::createIterator()const,we have class StackIter, then pointer on stack, I don't understand at all. Maybe when we write Stack s2(s1), it comes from here ?
So the meaning of iterator is shown in bool operator == (const Stack &l, const Stack &r) ?
Thanks a lot in advance .
Any response will be appreciated
#include <iostream>
using namespace std;
class Stack
{
int items[10];
int sp;
public:
friend class StackIter;
Stack()
{
sp = - 1;
}
void push(int in)
{
items[++sp] = in;
}
int pop()
{
return items[sp--];
}
bool isEmpty()
{
return (sp == - 1);
}
StackIter *createIterator()const; // 2. Add a createIterator() member
};
class StackIter
{
// 1. Design an "iterator" class
const Stack *stk;
int index;
public:
StackIter(const Stack *s)
{
stk = s;
}
void first()
{
index = 0;
}
void next()
{
index++;
}
bool isDone()
{
return index == stk->sp + 1;
}
int currentItem()
{
return stk->items[index];
}
};
StackIter *Stack::createIterator()const
{
return new StackIter(this);
}
bool operator == (const Stack &l, const Stack &r)
{
// 3. Clients ask the container object to create an iterator object
StackIter *itl = l.createIterator();
StackIter *itr = r.createIterator();
// 4. Clients use the first(), isDone(), next(), and currentItem() protocol
for (itl->first(), itr->first(); !itl->isDone(); itl->next(), itr->next())
if (itl->currentItem() != itr->currentItem())
break;
bool ans = itl->isDone() && itr->isDone();
delete itl;
delete itr;
return ans;
}
int main()
{
Stack s1;
for (int i = 1; i < 5; i++)
s1.push(i);
Stack s2(s1), s3(s1), s4(s1), s5(s1);
s3.pop();
s5.pop();
s4.push(2);
s5.push(9);
cout << "1 == 2 is " << (s1 == s2) << endl;
cout << "1 == 3 is " << (s1 == s3) << endl;
cout << "1 == 4 is " << (s1 == s4) << endl;
cout << "1 == 5 is " << (s1 == s5) << endl;
}

1) Default copy constructor operator:
Stack s2(s1) correcsponds to the Stack s2(const Stack& x) copy constructor, generated by your compiler if you don't tell him to use another one.
2) Definition of a member function
StackIter *Stack::createIterator()const { ...} is the definition of the member function createIterator() that is declared in you class but was not yet defined. Basically it returns a pointer to a StackIter.
3) definition of an operator
Not sure about your question.
bool operator == (const Stack &l, const Stack &r) defines the comparison between two stacks. So a priori not directly related to iterators.
But indeed, this function demonstrates the use of the iterators.
P.S: I think you are working on an example of this tutorial. I'd however warmly recommend you to read "The C++ Programming Language" or some similar books who give you full insight on working with iterator and address all the prerequisites.

Related

Template Classes in C++ and Function Overloading

I am practicing using templates and classes in C++. My goal is to write a template class for a deque. It will have functions to "insert_head", "insert_tail", "remove_tail", and "remove head", along with the ability to be printed using "cout". Also, the '=' operator must be able to be used to copy one instance of the class to another instance. Here is my current code:
#ifndef DEQUE_H
#define DEQUE_H
template <typename T>
class Deque {
public:
Deque(int size = 0, int capacity = 1000) : size_(size), capacity_(capacity)
{}
Deque(Deque & d) : x_(d.x()), size_(d.size()), capacity_(d.capacity()) {}
std::ostream & operator<<(std::ostream & cout) {
cout << '[';
if (size_ > 0) {
for (int i = 0; i < (size_ - 1)* sizeof(T); i += sizeof(T)) {
std::cout << *(x_ + i) << ',';
}
cout << *(x_ + (size_ - 1)* sizeof(T));
}
cout << ']';
return cout;
}
Deque operator=(Deque d) {
Deque dq(d);
return dq;
}
void print_test() {
std::cout << '[';
if (size_ > 0) {
for (int i = 0; i < (size_ - 1)* sizeof(T); i += sizeof(T)) {
std::cout << *(x_ + i) << ',';
}
std::cout << *(x_ + (size_ - 1)* sizeof(T));
}
std::cout << ']';
}
int * x() {
return x_;
}
int size() {
return size_;
}
int capacity() {
return capacity_;
}
bool is_empty() {
return size_ == 0;
}
void insert_tail(T tail) {
if (size_ < capacity_) {
*(x_ + sizeof(T) * size_) = tail;
size_++;
} else {
// throw overflow
}
}
T remove_tail() {
if (size_ > 0) {
T ret = *(x_ + sizeof(T) * (size_ - 1));
std::cout << ret;
size_--;
return ret;
} else {
// throw underflow
}
}
void insert_head(T head) {
if (size_ > 0 && size_ < capacity_) {
for (int i = (size_ - 1) * sizeof(T); i < 0; i -= sizeof(T)) {
*(x_ + i + sizeof(T)) = *(x_ + i);
}
}
if (size_ < capacity_) {
*x_ = head;
size_++;
} else {
// throw overflow
}
}
T remove_head() {
if (size_ > 0) {
T ret = *x_;
for (int i = sizeof(T); i < size_* sizeof(T); i += sizeof(T)) {
*(x_ + i - sizeof(T)) = *(x_ + i);
}
size_--;
return ret;
} else {
// throw underflow
}
}
private:
T * x_;
int size_;
int capacity_;
};
#endif
Here is my test code using that class:
#include <iostream>
#include "Deque.h"
int main(int argc, char const *argv[])
{
Deque< int > dq;
dq.insert_head(1);
// dq.insert_head(2); // adding head when not empty causes bug
dq.insert_tail(3);
dq.insert_tail(4);
dq.insert_tail(5);
dq.print_test(); std::cout << std::endl;
// std::cout << dq; // '<<' not overloaded properly'
std::cout << dq.remove_head() << " head removed\n";
// int x = dq.remove_head(); // seg faults when assigning returned value to a variable
dq.insert_tail(2);
dq.print_test();
std::cout << std::endl;
Deque< int > dq1(dq);
Deque< int > dq2;
// dq2 = dq1; // '=' not overloaded properly
return 0;
}
Each of my four problems is in a commented out line of code in my test file, here is a further explaination:
When "dq.insert_head(2)" is called and dq is not empty (size > 0) I try to shift all the other elements in the deque over one position so I can insert the new value there, there is a problem and the elements are not moved over.
"std::cout << dq" does not print dq like it should. The code is very similar to the "print_test()" method, however when I run the program I get the error "no match for operator <<". Is this because it is template class? Or am I doing something else completely wrong?
When trying to remove the head or tail from the deque, I am trying to return the value removed. In the line of code not commented out, the returned value is printed as it should, but the following line of code causes a seg fault. Is it because I'm trying to assign a template varabale to an integer variable?
My last issue is the '=' operator is not copying one instance of the class to another. My goal was to create a new instance of the class then return that instance (as you can see in the "Deque operator=(Deque d)") but that is not working as I hoped. What is the best way to overload the '=' function using template classes.
Thank you for your help, the answer to any of these questions is much appreciated.
All of your functions have issues:
Deque(int size = 0, int capacity = 1000) : size_(size), capacity_(capacity) {}
If you allows to specify a size, then you would have to allocate and initialize memory for those items. You should only specify capacity.
x_ is not initialized.
Assuming, you want a fixed capacity, then your constructor should be:
Deque(int capacity = 1000)
: size_(0)
, x_(new T[capacity])
, capacity_(capacity)
{
}
And even that is a simplified version as it would call the constructor for all items which might be inefficient and require that T has an accessible default constructor.
And now for the copy constructor:
The copy constructor should do deep copy. Otherwise, your program will (probably) crash after deleting the first Deque for which you have done copies as deleting an item twice is undefined behavior.
The prototype should take a constant reference as in: Deque(const Deque &other);
The code would look similar to this:
Deque(const Deque &other)
: capacity_(other.capacity_)
, x_(new T[other.capacity_])
, size_(other.size_)
{
for (int i = 0; i != size_; ++i)
{
x_[i] = other.x_[i];
}
}
For the <<, the prototype should be:
friend std::ostream & operator<<(std::ostream &cout, const T &data)
assuming it is declared inside the class to access private fields. You need to pass the data on which the operator works.
For the assignment operator, something like this could works:
Deque& operator=(const Deque &other)
{
// Use swap idiom...
Deque tmp(other);
// Swap pointers so old x_ get destroyed...
T *old_x = x_;
x_ = tmp.x_;
tmp.x_ = old_x;
// Usually one would use std::swap.
// Here as tmp get destroyed, it is not strictly to swap capacity_ and size_.
capacity_ = tmp.capacity_;
size_ = tmp.size_;
}
Now for the x() function:
- If you do a queue, you probably don't want to expose data so the function should be removed.
- If it was kept, the function should be const and returns a pointer to T: T *x() const; for the expected functionality.
size, capacity and is_empty should all be const member functions.
insert_tail and remove_tail problems have been explain in other people comments (in particular extraneous sizeof).
Similar problems for insert_head and remove_head also. In addition, the code that copy existing items could be refactored inside a private function to follows the DRY principle and avoid code duplication.
The answer to your first problem is to remove the sizeof(T) so you end up with this
for (int i = (size_ - 1); i > 0; i --) {
*(x_ + i + 1) = *(x_ + i);
}
The answer to your second problem is to change your declaration for your << overload to friend std::ostream & operator<<(std::ostream & x, Deque n) and initialize the body outside the class.
The answer to the third problem is that you can't return an int pointer which may point to a different block of memory location that what T could be.
The answer to the fourth question is to do the following:
Deque& operator=(const Deque& d) {
x_ = d.x_; // Deep copy
size_ = d.size_;
capacity_ = d.capacity_;
return *this;
}

C++ add value into stack subscript requires array or pointer type and warning

I'm new to programming in C++. Also new to implementing stacks. My objective is creating RPN Calculator using template stack. Cant use the built in stack classes.
I have everything so far and now I am stuck, I can't think of how to fix this problem. I am currently getting these errors:
Error C2109 subscript requires array or pointer type
Warning C4244 'return': conversion from 'double' to 'int', possible loss of data
This is my stack class:
#include<stack>
#define STACK_MAX 500
template<class T>
class RPNCalculator
{
private:
//Insanciating stack class
T data[STACK_MAX];
int size;
//stack<T> rpnstack;
public:
RPNCalculator() {
size = 0;
}
~RPNCalculator();
int Top() {
if (size == 0) {
fprintf(stderr, "Error: stack empty\n");
return -1;
}
return data[size - 1];
}
void push(T data); // pushes a new operand onto the stack
// the following operations are to be performed as defined for Reverse Polish Notation
// binary operators:
T value(); // returns the topmost value
void pop(); // returns the topmost value and pops it off the top
double add();
double subtract();
double multiply();
double divide();
// unary operators:
double square(); // squares the current value
double negate(); // negates, i.e. 3 becomes -3
bool isEmpty(); // tests to see if there are elements on the stack
void clear(); // clears out the stack
};
template<class T>
inline bool RPNCalculator<T>::isEmpty()
{
bool status;
if (!top)
status = true;
else
status = false;
return status;
}
template<class T>
void RPNCalculator<T>::clear()
{
}
template<class T>
inline RPNCalculator<T>::~RPNCalculator()
{
}
template<class T>
inline void RPNCalculator<T>::push(T data)
{
if (size < STACK_MAX)
data[size++] = data;
else
fprintf(stderr, "Error: stack full\n");
}
template<class T>
inline T RPNCalculator<T>::value()
{
return T();
}
template<class T>
inline void RPNCalculator<T>::pop()
{
if (size == 0)
fprintf(stderr, "Error: stack empty\n");
else
size--;
}
This is my main class:
#include <iostream>
#include "RPNCalculator.h"
#include <string>
#include <sstream>
using namespace std;
bool isOperator(const string& input);
void performOperation(const string& st, RPNCalculator<double>& rpnstack);
int main() {
cout << "Welcome to the RPN Calculator by AbdulFatai Saliu __D00168401" << endl;
cout << "Enter c to clear \n"
<< "s to square \n"
<< "n to negate \n"
<< "p to pop current value \n"
<< "q to quit \n"
;
RPNCalculator<double> rnpstack;
string input;
while (true) {
//Dispaly prompt
cout << ">> ";
//get user input
cin >> input;
//check for numeric values
double numereric;
if (istringstream(input) >> numereric) {
}
else if (isOperator(input)) {
}
else if (input == "q") {
return 0;
}
else {
cout << "Input Not Valid" << endl;
}
//check for operators
//check for exit
// display invalid value message
}
system("PAUSE");
//return 0;
}
bool isOperator(const string& input) {
string operators[] = { "-","+","*","/"};
for (int i = 0; i < 6; i++) {
if (input == operators[i]) {
return true;
}
}
return false;
}
void performOperation(const string& input, RPNCalculator<double>& rpnstack) {
double firstValue, secondValue, result;
firstValue = rpnstack.Top();
rpnstack.pop();
secondValue = rpnstack.Top();
rpnstack.pop();
if (input == "-") {
result = secondValue - firstValue;
}
else if (input == "+") {
result = secondValue + firstValue;
}
else if (input == "*") {
result = secondValue * firstValue;
}
else if (input == "/") {
result = secondValue / firstValue;
}
cout << result << endl;
rpnstack.push(result);
}
the problem seems to be coming from my push() method in the RPNCalculator template class.
Looks like you have a parameter for the function void push(T data); where the parameter has the same name as the class member (data, your storage). Try changing the parameter name in the function implementation that doesn't yield this conflict. You could also be specific which data you want to use if you really want to use that name.
Try this one instead
template<class T>
inline void RPNCalculator<T>::push(T arg)
{
if (size < STACK_MAX)
data[size++] = arg;
else
fprintf(stderr, "Error: stack full\n");
}
or, if you want to be explicit about which data you are assigning
template<class T>
inline void RPNCalculator<T>::push(T data)
{
if (size < STACK_MAX)
this->data[size++] = data; // this->data is the member, data is the function local variable
else
fprintf(stderr, "Error: stack full\n");
}
This is usually avoided by naming the member variables in a way where there can't be conflicts. One way is to prefix your members with m_, where data would become m_data. Feel free to use any style of code that you want, but I'd suggest avoiding conflicts (and the second approach) when possible.

Iterator pattern example giving error in c++ [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
#include <iostream>
using namespace std;
class Stack
{
int items[10];
int sp;
public:
friend class StackIter;
Stack()
{
sp = - 1;
}
void push(int in)
{
items[++sp] = in;
}
int pop()
{
return items[sp--];
}
bool isEmpty()
{
return (sp == - 1);
}
StackIter *createIterator() const // 2. Add a createIterator() member
};
class StackIter
{
// 1. Design an "iterator" class
const Stack *stk;
int index;
public:
StackIter(const Stack *s)
{
stk = s;
}
void first()
{
index = 0;
}
void next()
{
index++;
}
bool isDone()
{
return index == stk->sp + 1;
}
int currentItem()
{
return stk->items[index];
}
};
StackIter *Stack::createIterator() const
{
return new StackIter(this);
}
bool operator == (const Stack &l, const Stack &r)
{
// 3. Clients ask the container object to create an iterator object
StackIter *itl = l.createIterator();
StackIter *itr = r.createIterator();
// 4. Clients use the first(), isDone(), next(), and currentItem() protocol
for (itl->first(), itr->first(); !itl->isDone(); itl->next(), itr->next())
if (itl->currentItem() != itr->currentItem())
break;
bool ans = itl->isDone() && itr->isDone();
delete itl;
delete itr;
return ans;
}
int main()
{
Stack s1;
for (int i = 1; i < 5; i++)
s1.push(i);
Stack s2(s1), s3(s1), s4(s1), s5(s1);
s3.pop();
s5.pop();
s4.push(2);
s5.push(9);
cout << "1 == 2 is " << (s1 == s2) << endl;
cout << "1 == 3 is " << (s1 == s3) << endl;
cout << "1 == 4 is " << (s1 == s4) << endl;
cout << "1 == 5 is " << (s1 == s5) << endl;
}
Compilation Error :
main.cpp:25:5: error: 'StackIter' does not name a type
StackIter *createIterator()const // 2. Add a createIterator() member
main.cpp: In function 'bool operator==(const Stack&, const Stack&)':
main.cpp:68:22: error: 'const class Stack' has no member named 'createIterator'
StackIter *itl = l.createIterator();
main.cpp:69:22: error: 'const class Stack' has no member named 'createIterator'
StackIter *itr = r.createIterator();
What am I doing wrong?
You're missing a semicolon after "StackIter *createIterator()const". I added a semicolon. Then the program worked. There is no error.

Segmentation fault after allocating new memory

I am trying to return the root node of a BST. My recursive function involves using std::vector as a container for SPnodes (the tree node object) which during a single call is iterated over and a vector with fewer elements is passed up to the next call. Once the vector is of size 1, my function returns a new SPnode which is created by calling the copy constructor on the first (and only) element in nodeList, the vector container.
This is then passed through the wrapper function and then to the original caller.
Question
I understand that when the vector container goes out of scope it is destroyed, however I'm allocating new memory and copying the SPnodes so I don't understand how this could be causing the problem. So then, what is causing this? I doubt my problem is unique, but I can't seem to find an answer after going through countless SO questions.
Code
SPnode header:
#ifndef SPNODEOBJ_H
#define SPNODEOBJ_H
#include "IntervalObjects.h"
#include "IntervalObj.h"
#include "InVecObj.h"
#include "StandardLib.h"
// --- SPnode Class ------------------------------------------------------------
// SPnode (or Subpaving Node), is a node in a binary tree which contains a
// parameter "box" which is an InVec object, and a left and right child which
// are also SPnode objects. These SPnode objects are the resultant boxes from
// calling the expand method on m_box. This implementation allows for two
// important characteristics: there is a way to determine "where" a given box in
// a subpaving is by iterating over a node's left or right child, which in turn
// allows for greater efficiency; secondly, the tree structure gives a "history"
// of the subpaving, which allows for the determination of parent boxes.
class SPnode
{
private:
InVec m_box;
// left and right children of this SPnode object - note that these must be
// pointers in order to use them in the definition of the class, otherwise
// SPnode would reference itself in its definition
SPnode* m_left;
SPnode* m_right;
// a boolean sepcifying whether the SPnode m_box is in the given subpaving
bool m_inSP;
bool m_hasBeenIterated;
public:
SPnode(InVec box): m_box(box), m_left(NULL), m_right(NULL), m_inSP(true),
m_hasBeenIterated(false) {}
SPnode(const SPnode &ASP)
{
recConstructor(this, ASP);
}
void recConstructor(SPnode* const &parent, const SPnode &ASP);
void recDestructor(SPnode* const &ASP);
~SPnode() {delete m_left;
delete m_right;}
// getters and setters
InVec getBox() const {return m_box;}
SPnode* getLeft() const {return m_left;}
SPnode* getRight() const {return m_right;}
bool getInSP() const {return m_inSP;}
bool getIterated() const {return m_hasBeenIterated;}
void setBox(const InVec box) {m_box = box;}
void setLeft(SPnode* const p_node) {m_left = p_node;}
void setRight(SPnode* const p_node) {m_right = p_node;}
void setInSP(bool truth) {m_inSP = truth;} // when this is called truth
// should only be false
void setIterated(bool truth) {m_hasBeenIterated = truth;}
bool isLeaf() const;
friend std::ostream& operator<< (std::ostream &out, const SPnode &ASP);
SPnode operator=(const SPnode& ASP)
{
std::cout << "assignment called\n";
if (this == &ASP) return *this;
recConstructor(this, ASP);
return *this;
}
friend void expand(SPnode &ASP);
friend InVec lower(const InVec &box, const Interval &width, int axis);
friend InVec upper(const InVec &box, const Interval &width, int axis);
friend void mince(SPnode &ASP);
friend SPnode regularize(ImList &list, InVec box);
friend SPnode* recRegularize(std::vector<InVec> &list, SPnode &parentNode);
};
#endif
SPnode cpp file:
#include "SPnodeObj.h"
void SPnode::recConstructor(SPnode* const &parent, const SPnode &ASP)
{
parent->m_box = ASP.m_box;
parent->m_inSP = ASP.m_inSP;
parent->m_hasBeenIterated = ASP.m_hasBeenIterated;
if (ASP.isLeaf())
{
parent->m_left = NULL;
parent->m_right = NULL;
return;
}
if (ASP.m_left == NULL)
{
parent->m_left = NULL;
}
if (ASP.m_right == NULL)
{
parent->m_right = NULL;
}
if (ASP.m_left != NULL)
{
parent->m_left = new SPnode((ASP.m_left)->m_box);
}
if (ASP.m_right != NULL)
{
parent->m_right = new SPnode((ASP.m_right)->m_box);
}
if (ASP.m_left != NULL)
{
recConstructor(parent->m_left, *(ASP.m_left));
}
if (ASP.m_right != NULL)
{
recConstructor(parent->m_right, *(ASP.m_right));
}
}
bool SPnode::isLeaf() const
{
return (m_left == NULL && m_right == NULL);
}
std::ostream& operator<< (std::ostream &out, const SPnode &ASP)
{
if (ASP.m_right == NULL && ASP.m_left != NULL)
{
out << "SPnode(SPnode, " << ASP.m_box << ", NULL)";
}
else if (ASP.m_left == NULL && ASP.m_right != NULL)
{
out << "SPnode(NULL, " << ASP.m_box << ", SPnode)";
}
else if (ASP.m_left == NULL && ASP.m_right == NULL)
{
out << "SPnode(NULL, " << ASP.m_box << ", NULL)";
}
else
{
out << "SPnode(SPnode, " << ASP.m_box << ", SPnode)";
}
return out;
}
and my functions:
SPnode* listToTree (std::vector<InVec> boxList)
{
int counter = 0;
std::vector<SPnode> nodeList;
for (auto box : boxList)
{
nodeList.push_back(SPnode(box));
counter += 1;
}
//return recListToTree(nodeList);
//return new SPnode(*(recListToTree(nodeList)));
return recListToTree(nodeList);
}
SPnode* recListToTree (std::vector<SPnode> &nodeList)
{
std::cout << "nodelist size is: " << nodeList.size() << "\n";
if (nodeList.size() == 1)
{
return new SPnode(nodeList.at(0));
}
std::vector<SPnode> parentNodeList;
int counter = 0;
for (auto node : nodeList)
{
if (node.getIterated())
{
counter += 1;
continue;
}
if (counter + 1 == nodeList.size())
{
parentNodeList.push_back(SPnode(node.getBox()));
break;
}
if (node.getBox().isAdjacent(nodeList.at(counter + 1).getBox()))
{
SPnode newNode =
SPnode(node.getBox().combine(nodeList.at(counter + 1).getBox()));
if (lessThan(node.getBox(), nodeList.at(counter + 1).getBox()))
{
newNode.setLeft (new SPnode(node));
newNode.setRight(new SPnode((nodeList.at(counter + 1))));
}
else
{
newNode.setRight(new SPnode(node));
newNode.setLeft (new SPnode((nodeList.at(counter + 1))));
}
parentNodeList.push_back(SPnode(newNode));
nodeList.at(counter).setIterated(true);
nodeList.at(counter + 1).setIterated(true);
counter += 1;
}
else
{
parentNodeList.push_back(SPnode(node.getBox()));
nodeList.at(counter + 1).setIterated(true);
counter += 1;
}
}
recListToTree(parentNodeList);
}
Any help is appreciated!
recListToTree does not return a value on all paths, as there is not return at the end of the function (crank up the warning level in the compiler for it to tell you this). This garbage return value is the likely cause of your crashes.
Not related to the crash, but a memory leak problem, is that recConstructor is overly complicated (all those duplicated ifs) and will copy things twice (once via the copy constructor invoked by new, and once later by the recursive call to recConstructor).

Program crashes despite no logical errors [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm basically trying to reverse the stack by passing it to a function. However, the program just crashes when I run it and I can find no logical errors as I have even overloaded the assignment operator to deal with pointer data members.
#include <iostream>
using namespace std;
/***************************************************************************/
class AStack {
public:
AStack();
AStack(int);
~AStack();
AStack operator = (AStack s);
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
int capacity;
int* a;
int index = -1; // Index of the top most element
};
AStack::AStack() {
a = new int[25];
capacity = 25;
}
AStack::AStack(int size) {
a = new int[size];
capacity = size;
}
AStack::~AStack() {
delete[] a;
}
AStack AStack::operator = (AStack s) {
capacity = s.capacity;
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}
void AStack::push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int AStack::pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int AStack::top() {
if (index == -1) {
cout << "\n\nNo elements in the Stack\n\n";
return -1;
}
return a[index];
}
bool AStack::isEmpty() {
return (index == -1);
}
void AStack::flush() {
if (index == -1) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
while (index != -1) {
cout << a[index--] << " ";
}
cout << endl << endl;
}
/***************************************************************************/
void reverseStack(AStack& s1) {
AStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
/***************************************************************************/
int main() {
AStack s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
reverseStack(s1);
cout << "\n\nFlushing s1:\n";
s1.flush();
system("pause");
return 0;
}
You are not providing a copy-constructor, and your assignment operator takes the argument by value. The statement s1 = s2 creates a copy of s2 by calling the implicitly defined copy constructor that copies the pointer, then assigns to s1. At the end of the expression the copy is destroyed, calling delete [] on the pointer. At the end of the function the destructor for s2 runs and attempts to delete [] the same pointer again.
You need to provide a copy constructor that does the right thing.