This is my header file for my static stack class, which is straight copied from my text book like it was supposed to be
#ifndef STACK_H
#define STACK_H
#include <iostream>
using namespace std;
// Stack template
template <class T>
class Stack
{
private:
T *stackArray;
int stackSize;
int top;
public:
// Constructor
Stack(int);
// Copy constructor
Stack(const Stack&);
// Destructor
~Stack();
// Stack operations
void push(T);
void pop(T &);
bool isFull();
bool isEmpty();
};
//***************************************************
// Constructor *
//***************************************************
template <class T>
Stack<T>::Stack(int size)
{
stackArray = new T[size];
stackSize = size;
top = −1;
}
//***************************************************
// Copy constructor *
//***************************************************
template <class T>
Stack<T>::Stack(const Stack &obj)
{
// Create the stack array.
if (obj.stackSize > 0)
stackArray = new T[obj.stackSize];
else
stackArray = nullptr;
// Copy the stackSize attribute.
stackSize = obj.stackSize;
// Copy the stack contents.
for (int count = 0; count < stackSize; count++)
stackArray[count] = obj.stackArray[count];
// Set the top of the stack.
top = obj.top;
}
//***************************************************
// Destructor *
//***************************************************
template <class T>
Stack<T>::~Stack()
{
if (stackSize > 0)
delete[] stackArray;
}
//*************************************************************
// Member function push pushes the argument onto *
// the stack. *
//*************************************************************
template <class T>
void Stack<T>::push(T item)
{
if (isFull())
{
cout << "The stack is full.\n";
}
else
{
top++;
stackArray[top] = item;
}
}
//*************************************************************
// 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 Stack<T>::pop(T &item)
{
if (isEmpty())
{
cout << "The stack is empty.\n";
}
else
{
item = stackArray[top];
top--;
}
}
//*************************************************************
// Member function isFull returns true if the stack *
// is full, or false otherwise. *
//*************************************************************
template <class T>
bool Stack<T>::isFull()
{
bool status;
if (top == stackSize − 1)
status = true;
else
status = false;
return status;
}
//*************************************************************
// Member function isEmpty returns true if the stack *
// is empty, or false otherwise. *
//*************************************************************
template <class T>
bool Stack<T>::isEmpty()
{
bool status;
if (top == −1)
status = true;
else
status = false;
return status;
}
#endif
this is my main.cpp
#include "Stack.h"
#include <stack>
#include <string>
int PostfixCalculator(string postfixExpression);
bool isOperator(const string& expression);
void performOp(const string& expression, stack<int>& calc);
int main(){
string expression;
cout << "Enter Postfix Expression" << endl;
cin >> expression;
PostfixCalculator(expression);
}
bool isOperator(const string& expression){
string ops[] = { "-", "+", "*", "/" };
for (int i = 0; i < 4; i++){
if (expression == ops[i]){
return true;
}
}
return false;
}
void performOp(const string& expression, Stack<int>& calc){//const
int leftVal, rightVal, result;
calc.pop(rightVal);
calc.pop(leftVal);
if (expression == "-"){
result = leftVal - rightVal;
}
else if (expression == "+"){
result = leftVal + rightVal;
}
else if (expression == "*"){
result = leftVal * rightVal;
}
else{
result = leftVal / rightVal;
}
cout << result << endl;
calc.push(result);
};
int PostfixCalculator(string expression){
int num;
int size = expression.size();
Stack<int> calc(size);
Stack<int> copyCalc(calc);
for (int i = 0; i < expression.size(); i++){
char c = expression.at(i);
if (c >= '0' && c <= '9'){
c = num;
copyCalc.push(num);
}
else if (isOperator(expression)){
performOp(expression, copyCalc);
}
}
};
I keep getting this error: "Error 2 error C2065: '−1' : undeclared identifier
The error is happening here:
template <class T>
Stack<T>::Stack(int size)
{
stackArray = new T[size];
stackSize = size;
top = −1;
}
it happens at "top = -1"
The −1 is not using the ASCII minus sign, but instead it's a typographical punctuation. Try using -1 instead.
Related
vector<int> a = {1,2,3};
a[1] = 54; // I want to achieve this in my Darray implementation
int i = 0;
a[i] = 10 // This also
I am trying to implement dynamic arrays in c++. Below is my code :
//-------- means it has not been defined yet
// custom Exception class for handling bizzare situations
#include <iostream>
using namespace std;
class MyException {
public:
MyException() {
cout << "\nException occured !! Program will terminate...\n";
exit(0);
}
MyException(string message) {
cout << "\nException occured : " << message
<< ".\nProgram will terminate...\n";
exit(0);
}
};
//================================================================================
// class for Dyanamic array
template <typename T> //
class Darray {
T *arr; // Dyanamic array
size_t len, cap; // length and capacity
/*
len : number of elements currently Darray contains
cap : number of elements Darray can hold without resizing
*/
public:
Darray();
Darray(size_t);
Darray(Darray<T> &);
// Darray(T *); //---------------
size_t capacity();
size_t length();
void resize(size_t);
bool empty();
T operator[](int);
T operator[](T);
void operator=(T); //-------------
void operator=(Darray);
void push(T);
T pop();
T back();
T elemAt(int);
T front();
T *data();
void assign(Darray); //---------------
void assign(T *); //--------------
void insertAt(T, int); //--------------
void erase(); //-------------
void clear(); //---------------
void swap(Darray, Darray); //---------
};
//================================================================================
// default constructor for 0 capacity
template <typename T> //
Darray<T>::Darray() {
arr = new T[0];
len = 0;
cap = 0;
}
//================================================================================
// parameterized constructor with given cap
template <typename T> //
Darray<T>::Darray(size_t cap) {
arr = new T[cap];
this->cap = cap;
len = 0; // no elements initially
}
//================================================================================
// copy constructor with given Darray
template <typename T> //
Darray<T>::Darray(Darray<T> &temp) {
cap = temp.capacity();
len = 0;
arr = new T[cap];
while (len < temp.length()) {
arr[len] = temp[len];
len++;
}
}
//================================================================================
// operator[] for getting elements
template <typename T> //
T Darray<T>::operator[](int index) {
if (empty())
throw MyException("Darray is empty");
if (index < 0 || index > len - 1)
throw MyException("Invalid index. Index should be in range 0 to length-1");
return arr[index];
}
//================================================================================
// to check if Darray is empty
template <typename T> //
bool Darray<T>::empty() {
return len < 1;
}
//================================================================================
// push elements at the end
template <typename T> //
void Darray<T>::push(T element) {
if (len == cap)
resize(cap + (cap / 2) + 1); // resizing the array
// +1 to ensure arrays of size 0 or 1 are also resized ;-)
arr[len] = element;
len++;
}
//================================================================================
// remove and gives the last element of Darray
template <typename T> //
T Darray<T>::pop() {
if (empty())
throw MyException("Darray is empty");
return arr[--len];
}
//================================================================================
// gives the last element of Darray
template <typename T> //
T Darray<T>::back() {
if (empty())
throw MyException("Darray is empty");
return arr[len - 1];
}
//================================================================================
// gives the first element of Darray
template <typename T> //
T Darray<T>::front() {
if (empty())
throw MyException("Darray is empty");
return arr[0];
}
//================================================================================
// gives element at pos
template <typename T> //
T Darray<T>::elemAt(int index) {
if (empty())
throw MyException("Darray is empty");
if (index < 0 || index > len - 1)
throw MyException("Invalid index. Index should be in range 0 to length-1");
return arr[index];
}
//================================================================================
// length gives number of elements currently present in the array
template <typename T> //
size_t Darray<T>::length() {
return len;
}
//================================================================================
// capacity gives total capacity of the array
template <typename T> //
size_t Darray<T>::capacity() {
return cap;
}
//================================================================================
// returns a pointer to first element of Darray
template <typename T> //
T *Darray<T>::data() {
if (empty())
return NULL;
return arr;
}
//================================================================================
// resize the array to given size
template <typename T> //
void Darray<T>::resize(size_t newSize) {
if (newSize < 0)
throw MyException("Size cannot be negative");
if (newSize == cap) // no need to resize
return;
T *temp; // temp array to hold the elements temporarily
size_t t; // t holds the number of elements to be copied in the resized Darray
if (newSize < len) {
t = newSize;
temp = new T[newSize];
// copying to temp,new size is less, some elements will be lost
for (int i = 0; i < t; i++) {
temp[i] = arr[i];
}
} else {
t = len;
temp = new T[len];
// copying all the elements from original array to temp
for (int i = 0; i < t; i++) {
temp[i] = arr[i];
}
}
arr = new T[newSize]; // resizing the Darray
// copying elements from temp to original Darray
for (int i = 0; i < t; i++) {
arr[i] = temp[i];
}
cap = newSize;
len = t;
}
int main()
{
Darray<char> a(0);
a.push('A');
a.push('B');
a.push('C');
a.push('D');
a.push('E');
// a.push('F');
// a.push('G');
// a.push('H');
for (int i = 0; i < a.length(); i++) {
cout << a[i] << " ";
}
cout << a.length() << " " << a.capacity() << endl;
return 0;
}
Is overloading the assignment operator to assign elements at given index of my dynamic array possible?
Something like:
Darray<int> a(5);
a[1] = 26;
Also if I overload the constructor to take array as T* and create a Darray(0) it becomes ambiguous (null pointer and Darray of size 0).
How to overcome this?
Your subscript operator returns by value. That means it returns a brand new copy.
Assigning to this copy will not change the original inside your "array".
You should return by reference instead:
T& operator[](int);
And you should probably add a "constant" overload as well:
T const& operator[](int) const;
Debug Assertion Failed!
Program: ...nts\Visual Studio 2015\Projects\Project 5\Debug\Project 5.exe
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line: 892
Expression: is_block_type_valid(header->_block_use)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
The program runs and outputs everything correctly, and throws this error. I haven't been able to find any good explanations of what this means or how to go about finding or fixing it. Here is a complete copy of the (incredibly ugly and badly written) code:
#include <iostream>
using namespace std;
/* a class for storing a Binary Tree */
template <class Type>
class BinaryTree {
protected:
Type parentArray[10];
Type childArray[10];
public:
BinaryTree();
BinaryTree(int& k);
~BinaryTree();
BinaryTree(BinaryTree<Type>& bt);
void operator= (BinaryTree<Type>& bt);
friend ostream& operator<< (ostream& s, BinaryTree<Type> bt) {
s << "[ ";
bt.inorder(bt.getRoot());
s << "]" << endl;
return s;
};
int size();
int height();
int getLeft(int k);
int getRight(int k);
void preorder(int k);
void inorder(int k) {
// do I have a left child?
if ((getLeft(k)) != -1) {
// if yes inorder (left child)
inorder(getLeft(k));
};
// output k
cout << k << " ";
// do I have a right child?
if ((getRight(k)) != -1) {
// if yes inorder (right child)
inorder(getRight(k));
};
};
void postorder(int k);
void setRoot(Type& val);
void setParent(Type* child, Type* parent);
void setLeft(Type& val);
void setRight(Type& val);
int getRoot();
};
/* default constructor */
template <class Type>
BinaryTree<Type>::BinaryTree() {
parentArray = new ArrayClass<Type>();
childArray = new ArrayClass<Type>();
};
/* non-empty constructor */
template <class Type>
BinaryTree<Type>::BinaryTree(int& k) {
// parentArray = new Type[k];
// childArray = new Type[k];
};
template <class Type>
BinaryTree<Type>::~BinaryTree() {
delete[] parentArray;
delete[] childArray;
};
template <class Type>
BinaryTree<Type>::BinaryTree(BinaryTree<Type>& bt) {
for (int i = 0; i < bt.size(); i++) {
parentArray[i] = bt.parentArray[i];
childArray[i] = bt.childArray[i];
};
};
template <class Type>
void BinaryTree<Type>::operator= (BinaryTree<Type>& bt) {
};
/* return the size of the tree using the length of the parent array */
template <class Type>
int BinaryTree<Type>::size() {
return (sizeof(parentArray)/sizeof(*parentArray));
};
template <class Type>
int BinaryTree<Type>::height() {
return 5;
};
template <class Type>
int BinaryTree<Type>::getLeft(int k) {
// if the parent array value of the given number is k and
// the child array value indicates it is a left child
for (int i = 0; i < size(); i++) {
if ((parentArray[i] == k) && (childArray[i] == 0)) {
// return that value
return i;
};
};
return -1;
};
template <class Type>
int BinaryTree<Type>::getRight(int k) {
// if the parent array value of the given number is k and
// the child array value indicates it is a right child
for (int i = 0; i < size(); i++) {
if ((parentArray[i] == k) && (childArray[i] == 1)) {
// return that value
return i;
};
};
return -1;
};
template <class Type>
void BinaryTree<Type>::preorder(int k) {
// output k
cout << k << " ";
// do I have a left child?
if ((getLeft(k)) != -1) {
// if yes preorder left child
preorder(getLeft(k));
};
// do I have a right child?
if ((getRight(k)) != -1) {
// if yes preorder right child
preorder(getRight(k));
};
};
template <class Type>
void BinaryTree<Type>::postorder(int k) {
// do I have a left child?
if ((getLeft(k)) != -1) {
// if yes inorder (left child)
inorder(getLeft(k));
};
// do I have a right child?
if ((getRight(k)) != -1) {
// if yes inorder (right child)
inorder(getRight(k));
};
// output k
cout << k << " ";
};
template <class Type>
void BinaryTree<Type>::setRoot(Type& val) {
// if the given value is the root of the tree then set
// its index in the parent and child arrays to -1
parentArray[val] = -1;
childArray[val] = -1;
};
template <class Type>
void BinaryTree<Type>::setParent(Type* child, Type* parent) {
// set a given value as the parent of a given value
parentArray[(*child)] = *parent;
};
template <class Type>
void BinaryTree<Type>::setLeft(Type& val) {
// set a given value in the child array to indicate a left child
childArray[val] = 0;
};
template <class Type>
void BinaryTree<Type>::setRight(Type& val) {
// set a given value in the child array to indicate a right child
childArray[val] = 1;
};
template <class Type>
int BinaryTree<Type>::getRoot() {
// find the root value of the tree
for (int i = 0; i < size(); i++) {
if (parentArray[i] == -1) {
// and return it
return i;
};
};
};
int main() {
int* val1 = new int;
int* val2 = new int;
int* val3 = new int;
int count;
cin >> count;
BinaryTree<int> bt(count);
for (int i = 0; i < count; i++) {
cin >> *val1;
cin >> *val2;
cin >> *val3;
if (i == 0) {
bt.setRoot(*val1);
};
if (*val2 != -1) {
bt.setParent(val2, val1);
bt.setLeft(*val2);
}
if (*val3 != -1) {
bt.setParent(val3, val1);
bt.setRight(*val3);
}
val1 = new int;
val2 = new int;
val3 = new int;
};
cout << bt.size() << endl;
bt.postorder(bt.getRoot());
cout << endl;
bt.preorder(bt.getRoot());
cout << endl;
delete val1;
delete val2;
delete val3;
};
Some of the functions in the BinaryTree class aren't finished yet and just have filler garbage in them for testing.
Your BinaryTree destructor always makes sure to:
delete[] parentArray;
delete[] childArray;
Unfortunately, one of the class's constructors does not new any of these arrays. As such, the destructor ends up attempting to delete a pair of uninitialized garbage pointers.
It's also possible that this class violates the Rule Of The Three, but I have not analyzed this sufficiently.
EDIT: as it's been pointed out in the comments, these are not pointers; so this is wrong anyway, but for other reasons.
I have method of class Stack, which compares 2 objects of this class:
bool comparison(T &stack) {
if (size == stack.size)
for (int i = 0; i < size; i++) {
if (!this->stackPr[i].comparison(stack.stackPr[i]))
return false;
}
else
return false;
return true;
}
and uses the method of class Time:
bool comparison(Time &time) {
if ((this->hours == time.hours) && (this->minutes == time.minutes) && (this->seconds == time.seconds))
return true;
return false;
When I try to use this comman in main:
bool temp = stack3.comparison(stack4);
MVS underlines |stack4| and shows me the error:
a reference of type "Time &"(non-const qualified) cannot be initialized with a value of type Stack<Time>
How could I handle this problem?
Thanks for your answers :)
There is class Stack:
class Stack {
private:
T *stackPr;
int size;
int top;
public:
//----------------CONSTRUCTORS-----------------
Stack(int n) {
if (n > 0)
size = n;
else
size = 10;
stackPr = new T[size];
top = -1;
}
Stack() {
size = 10;
stackPr = new T[size];
top = -1;
}
Stack(Stack &stack) {
stackPr = new T[stack.size];
size = stack.size;
top = stack.top;
for (int i = 0; i < size; i++)
stackPr[i] = stack.stackPr[i];
}
Stack(T *objs, int sizeMass) {
size = sizeMass;
stackPr = new T[size];
for (int i = 0; i < sizeMass; i++) {
this->push(objs[i]);
}
}
//----------------DESTRUCTOR-------------------
~Stack() {
delete[] stackPr;
}
//-----------------METHODS---------------------
//Add element to stack
void push(T &element) {
if (top == size - 1)
cout << "\nThere's no more place!!!\n";
else {
top++;
stackPr[top] = element;
cout << "\nElement was succesfully pushed\n";
}
}
//Read + Delete
T pop() {
if (top == -1)
cout << "\nStack is empty\n";
else {
T temp = stackPr[top];
stackPr[top] = 0;
top--;
cout << "\nElement was succesfully poped and deleted\n";
return temp;
}
}
//Read
T popup() {
if (top == -1)
cout << "\nStack is empty\n";
else {
cout << "\nElement was succesfully popped\n";
return stackPr[top];
}
}
//Comparison of 2 stacks
bool comparison(T &stack) {
if (size == stack.size)
for (int i = 0; i < size; i++) {
if (!this->stackPr[i].comparison(stack.stackPr[i]))
return false;
}
else
return false;
return true;
}
};
Try this, in your Stack class
change:
bool comparison(T &stack) {
for this:
bool comparison(Stack<T> &stack) {
First of all, abandon this comparison function, it hinders your code, use == instead.
Secondly, use const Stack<T> in your comparison function.
And finally, use auto to deduce the type of the variables.
Here is an example that shows the basics of what I just wrote:
#include <iostream>
using namespace std;
struct Time
{
bool operator==(const Time& time)
{
return true;// adjust it with your own needs.
}
};
template<typename T>
struct Stack
{
T val;
Stack(T& val_): val(val_) {}
bool operator==(const Stack<T>& stack)
{
return this->val == stack.val; // here is your business logic of comparison
}
};
int main()
{
Time t1;
Time t2;
Stack<Time> myStack1(t1);
Stack<Time> myStack2(t2);
auto temp = myStack1 == myStack2;
cout << temp << endl;
return 0;
}
I'm trying to work with this heap. I'm inserting a few random numbers then removing them to make sure my heap works. The problem is when I'm removing them I get duplicate numbers that shouldn't exist in the Heap. Pretty much I'll insert the following numbers and get back in return: 5 2 10 10 for some reason.
My main looks like this:
#include <iostream>
#include <fstream>
using namespace std;
#include "heap.h"
int main(void)
{
Heap<int> inlist(4);
inlist.insert(5);
inlist.insert(2);
inlist.insert(3);
inlist.insert(10);
int test;
while(inlist.remove(test))
cout << test << endl;
}
And my Heap looks like this:
#ifndef HEAP_H
#define HEAP_H
template<typename TYPE>
class Heap
{
private:
TYPE* heapData;
int currSize;
int capacity;
void _siftUp(int);
void _siftDown(int);
int _leftChildOf(int) const;
int _parentOf(int) const;
public:
Heap(int c = 100);
~Heap();
bool viewMax(TYPE&) const;
int getCapacity() const;
int getCurrSize() const;
bool insert(const TYPE&);
bool remove(TYPE&);
};
template<typename TYPE>
Heap<TYPE>::Heap(int c = 100)
{
capacity = 100;
currSize = 0;
heapData = new TYPE[capacity];
}
template<typename TYPE>
Heap<TYPE>::~Heap()
{
delete[] heapData;
currSize = 0;
capacity = 0;
}
template<typename TYPE>
bool Heap<TYPE>::insert(const TYPE& dataIn)
{
bool success = false;
if(currSize < capacity)
{
heapData[currSize] = dataIn;
_siftUp(currSize);
currSize++;
success = true;
}
return success;
}
template<typename TYPE>
void Heap<TYPE>::_siftUp(int child)
{
TYPE temp;
int parent;
if(child > 0)
{
parent = _parentOf(child);
if(heapData[child] > heapData[parent])
{
temp = heapData[parent];
heapData[parent] = heapData[child];
heapData[child] = temp;
_siftUp(child);
}
}
}
template<typename TYPE>
bool Heap<TYPE>::remove(TYPE& dataOut)
{
bool success = false;
if(currSize > 0)
{
dataOut = heapData[0];
currSize--;
heapData[0] = heapData[currSize];
_siftDown(0);
success = true;
}
return success;
}
template<typename TYPE>
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int child = _leftChildOf(parent);
if(child < currSize)
{
if((child + 1 < currSize) && (heapData[child] < heapData[child + 1]))
child++;
if(child)
{
temp = heapData[child];
heapData[child] = heapData[child + 1];
heapData[child + 1] = temp;
_siftDown(child);
}
}
}
template<typename TYPE>
int Heap<TYPE>::_leftChildOf(int p) const
{
return(2 * p + 1);
}
template<typename TYPE>
int Heap<TYPE>::_parentOf(int c) const
{
return((c - 1) / 2);
}
//**************************************************************************
template<typename TYPE>
int Heap<TYPE>::getCapacity() const
{
return capacity;
}
template<typename TYPE>
int Heap<TYPE>::getCurrSize() const
{
return currSize;
}
template<typename TYPE>
bool Heap<TYPE>::viewMax(TYPE& max) const
{
return false;
}
#endif
I'm pretty sure the problem isn't when I'm inserting into my Heap but when I'm removing it.
EDIT I changed my _siftDown a bit - now the numbers show up 5 10 3 2
if(child)
{
temp = heapData[child];
heapData[child] = heapData[parent];
heapData[parent] = temp;
_siftDown(child);
}
Your _siftDown is broken,
template<typename TYPE>
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int child = _leftChildOf(parent);
if(child < currSize)
{
if((child + 1 < currSize) && (heapData[child] < heapData[child + 1]))
child++;
if(child)
What's that meant to check? child is at this point either 2*parent + 1 or 2*parent + 2, without overflow, since parent should always be >= 0, that is always positive ~> condition fulfilled.
You need to check whether you want to swap heapData[parent] and heapData[child], so that condition should be if (heapData[parent] < heapData[child]).
{
temp = heapData[child];
heapData[child] = heapData[child + 1];
heapData[child + 1] = temp;
You are swapping the elements at index child and child+1, that's wrong. You should swap heapData[child] and heapData[parent] here.
_siftDown(child);
}
}
}
You also have an error in _siftUp,
template<typename TYPE>
void Heap<TYPE>::_siftUp(int child)
{
TYPE temp;
int parent;
if(child > 0)
{
parent = _parentOf(child);
if(heapData[child] > heapData[parent])
{
temp = heapData[parent];
heapData[parent] = heapData[child];
heapData[child] = temp;
_siftUp(child);
}
}
}
the recursive call should be _siftUp(parent), otherwise you never sift any item up more than one level.
Your remove method is good while your _siftDown has something wrong.
It's not always true that you siftdown with your left child.
void Heap<TYPE>::_siftDown(int parent)
{
TYPE temp;
int left= _leftChildOf(parent);
int right= _rightChildOf(parent);
int max= parent;
if(left< currSize && heapData[left] > heapData[max])
{
max= left;
}
if(right< currSize && heapData[right] > heapData[max])
{
max= right;
}
if( max!=parent ) //need to sift down
{
temp = heapData[max];
heapData[max] = heapData[parent];
heapData[parent] = temp;
_siftDown(max);
}
}
}
You can use the following functions instead of implementing your own heap:
std::make_heap
std::push_heap
std::pop_heap
You can find them in the algorithm header
heapData[0] = heapData[currSize];
Here you should not use heapData[currSize] otherwise you are copying the last elemnt of the heap to the top.
For example after removing 5 from the heap currSize is 3 and you do
heapData[0] = heapData[3];
which will create a duplicate of 10 at heapData[0].
Without taking a closer look on your code
You realize that test is never initialized?
int test; //initialization should happen here
while(inlist.remove(test))
cout << test << endl;
I also do not understand what the purpose of the parameter at Heap::remove(dataOut) is. Would it differ from Heap::remove(void) ?
This is my first pathetic attempt at C++. I did an array based stack in C++ and the destructor is throwing out some memory dump. I can't figure out what went wrong.
#include <stdio.h>
#include <iostream>
#include <exception>
using namespace std;
class FullStackException : public exception {
virtual const char* what() const throw() {
return "Stack is full.";
}
} fsex;
class EmptyStackException : public exception {
virtual const char* what() const throw() {
return "Stack is empty.";
}
} esex;
template <class D>
class ArrayBasedStack {
private:
int t; //t represents top
D *S;
int arrSize;
public:
ArrayBasedStack(int arraySize = 10);
~ArrayBasedStack();
int size(); /*returns the number of elements stored*/
void push(D&); /*inserts an element*/
D pop(); /*removes and returns the last inserted element*/
D top(); /*returns the last inserted element without removing it*/
int isEmpty(); /*indicates whether no elements are stored*/
};
template <class D>
ArrayBasedStack<D>::ArrayBasedStack(int arraySize) {
/* Elements are added from left to right */
S = new D[arraySize];
arrSize = arraySize;
/* t keeps track of the index of the top element */
t = -1;
}
template <class D>
ArrayBasedStack<D>::~ArrayBasedStack() {
if(S != NULL) {
int i = 0;
for(i = 0; i < size(); i++) {
S[i] = NULL;
}
cout << "about to delete S" << endl;
delete[] S;
}
}
template <class D>
int ArrayBasedStack<D>::size() {
return t;
}
template <class D>
void ArrayBasedStack<D>::push(D& data) {
if(t == arrSize) {
throw fsex;
} else {
S[t] = data;
t++;
}
}
template <class D>
D ArrayBasedStack<D>::pop() {
if(isEmpty()) {
throw esex;
}
D element = S[t];
S[t--] = NULL;
return element;
}
/*
* returns true if the stack is empty, false otherwise
*/
template <class D>
int ArrayBasedStack<D>::isEmpty() {
return (t < 0);
}
int main(int argc, char *argv[]) {
char inputs[][10] = {
"str1"
};
char *i = NULL;
ArrayBasedStack<char *> stack;
i = inputs[0];
stack.push(i);
try {
stack.pop();
}
catch(exception& ex) {
cout << "ERR:" << ex.what() << endl;
}
return 0;
}
The problem line is
t = -1;
Should be
t = 0;
because when you add first element, the following code is excecuted
} else {
S[t] = data; // t == -1
t++;
}
The following is the culprit.
template <class D>
void ArrayBasedStack<D>::push(D& data) {
if(t == arrSize) {
throw fsex;
} else {
S[t] = data; // Should be S[++t] = data;
t++; // Comment out this line
}
}
This implemntation assumes that 't' points to the topmost element on the stack rather than to the next available location for push
Note that operator [] and operator ++ have same precedence. Since they associate left-to-right, [] is evaluated before operator ++.
In your implementation, here is the problem. With t being initialized to -1, you are overwriting beyond the array subscript that is at S[-1] which leads to undefined behavior.
At least on my system the problem surfaces while trying to free the memory in destructor of the stack class. This is a classic example of a syptom being visible much after the goof-up has happened
Also would suggest push to take the parameters as D const &