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 &
Related
I am trying to write a generic Queue in the form of an array. Everything seems to work if I set the arraySize to a specific value but if I attempt to grow the array every time it becomes full it is causing the values to be overwritten. I appreciate any suggestions as to what I am doing wrong. Thanks
HEADER:
#ifndef QUEUE_ARRAY
#define QUEUE_ARRAY
template <typename E>
class Queue {
public:
Queue(); //constructor
//Queue(const Queue &obj); //copy constructor note:the copy constructor is optional
~Queue(); //destructor
void enqueue(const E& e);
const E& dequeue(); //throw(QueueEmpty); //note that the use of exceptions is optional
const E& front() const; //throw(QueueEmpty); //note that the use of exceptions is optional
int size() const;
bool empty() const;
private:
int frontElem, rear, numEntries, arraySize;
E* queueArray;
};
#endif //
QA CPP:
#include "QueueArray.h"
#include <iostream>
template<typename E>
Queue<E>::Queue() {
numEntries = 0;
arraySize = 1;
frontElem = 0;
rear = 0;
queueArray = new E[arraySize];
}
template<typename E>
Queue<E>::~Queue() {
delete[] queueArray;
}
template<typename E>
void Queue<E>::enqueue(const E & e) {
if (numEntries == arraySize) {
arraySize = arraySize * 2;
E* temp = new E[arraySize];
for (int i = 0; i < numEntries; i++) {
temp[i] = queueArray[(frontElem + i) % arraySize];
}
delete queueArray;
queueArray = temp;
}
queueArray[rear] = e;
rear = (rear + 1) % arraySize;
numEntries++;
}
template<typename E>
const E& Queue<E>::dequeue() {
E &temp = queueArray[frontElem];
frontElem = ((frontElem + 1) % arraySize);
numEntries--;
return temp;
}
template<typename E>
const E& Queue<E>::front() const {
return queueArray[frontElem];
}
template<typename E>
int Queue<E>::size() const {
return numEntries;
}
template<typename E>
bool Queue<E>::empty() const {
return (numEntries == 0);
}
QA EXPAND:
#include "QueueArray.cpp"
using namespace std;
template class Queue<int>;
QA TEST:
#include "QueueArray.h"
#include <iostream>
using namespace std;
int main() {
Queue<int> *s;
s = new Queue<int>();
for (int i = 1; i <= 25; i++){
s->enqueue(i);
}
while (!s->empty()) {
cout << "Dequeue: " << s->dequeue() << endl;
}
system("PAUSE");
delete s;
}
When you copy the existing queue data into the newly allocated buffer in enqueue, you copy the element at element frontElem to element 0. What you don't have, and need, is frontElem = 0; after copying the data. rear will also need to be updated.
And delete queueArray should be delete [] queueArray. Since you're allocating arrays, you need to delete arrays.
from the main.cpp
assert error is here
if(!((CPU1.peek()).isExecuting())) {
cout << "Running: " << CPU1.peek().running << endl;
(CPU1.peek()).execute();
cout << "Running: " << CPU1.peek().running << endl;
assert((CPU1.peek()).isExecuting());
((PCB)CPU1.peek()).setStart(slice);
((PCB)CPU1.peek()).setWait(slice-((PCB)CPU1.peek()).getArrival());
averageWait1 += ((PCB)CPU1.peek()).getWait();
cpu1PCBTotal++;
length1 = ((PCB)CPU1.peek()).getLength();
}
PCB.h
class PCB
{
private:
/**
* this process ID
*/
int pid;
/**
* the nice (priority) value of this process
*/
int priority;
/**
* running status 0=idle 1=running
*/
int running;
public:
/**
* Creates a simulated job with default values for its parameters.
*/
PCB()
{
priority = 19;
running = 0;
arrived = 0;
length = 0;
}
PCB(int id, int pval, int run, int arr, int len)
{
pid = id;
priority = pval;
running = run;
arrived = arr;
length = len;
}
bool isExecuting() const
{
return (running == 1);
}
void execute()
{
running = 1;
}
heap.cpp
template <typename E>
Heap<E>::Heap()
{
// compiler-generated code .. no need to implement this
}
template <typename E>
Heap<E>::~Heap()
{
while(tree.size() > 0)
tree.pop_back();
}
template <typename E>
bool Heap<E>::isEmpty() const
{
return tree.size() == 0;
}
template<typename E>
void Heap<E>::insert(E item)
{
tree.push_back(item);
int place = size()-1;
int parent = (place-1)/2;
while(parent >= 0 && tree[place] > tree[parent]) {
swap(place, parent);
place = parent;
parent = (place-1)/2;
}
}
template<typename E>
E Heap<E>::remove() throw (HeapException)
{
E root = tree[0];
tree[0] = tree[size()-1];
tree.pop_back();
reheapify(0);
return root;
}
template<typename E>
const E& Heap<E>::peek() const throw (HeapException)
{
return tree[0];
}
template<typename E>
int Heap<E>::size()const
{
return tree.size();
}
template<typename E>
void Heap<E>::swap(int place, int parent)
{
E temp = tree[place];
tree[place] = tree[parent];
tree[parent] = temp;
}
template<typename E>
void Heap<E>::reheapify(int root)
{
int l = root*2+1;
int r = root*2+2;
if(l < size()-1) {
if(r < size()-1)
if(tree[root] < tree[r]) {
swap(root, r);
reheapify(r);
}
if(tree[root] < tree[l]) {
swap(root, l);
reheapify(l);
}
}
}
The assertion is failing, and I have no idea why... Please help, thanks
Top is main function, bottom is PCB.h; CPU class is a Heap
Originally typecasted CPU1.peek() because it gave me the error "passing 'const PCB' as 'this' argument discards qualifiers" So I guess I needs help calling CPU1.peek().execute()
As the title says I am trying to implement Set ADT on a Hashtable with independent lists. The thing is I don't know where I'm wrong.
The code I am about to post is taken from a bigger project and I took just the esential parts of it to show you.
SetADT.h:
#pragma once
#pragma once
#include <stdio.h>
#define CAPACITY 10
using namespace std;
template <typename TElement>
class IteratorSet;
template<typename TElement>
class Set {
class Nod {
public:
TElement element;
Nod* next;
};
public:
Set();
void add(TElement element);
int size();
void sterge(TElement element);
bool cauta(TElement element);
friend class IteratorSet<TElement>;
IteratorSet<TElement> iterator() { return IteratorSet<TElement>(this); }
private:
int dimensiune;
typename Set<TElement>::Nod* prim;
int max;
Nod** table;
int hashFunction(TElement element) { return element.hashCode() % max; }
Nod* set;
};
template<typename TElement>
Set<TElement>::Set()
{
max = CAPACITATE;
table = new Nod*[max];
for (int i = 0; i < max; i++)
table[i] = NULL;
}
template <typename TElement>
void Set<TElement>::add(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
while (curent != NULL && !(element == curent->element))
curent = curent->next;
if (curent != NULL)
return;
else
{
Nod* n = new Nod;
n->element = element;
n->next = table[pozitie];
table[pozitie] = n;
}
dimensiune++;
}
template <typename TElement>
int Set<TElement>::size()
{
return dimensiune;
}
template <typename TElement>
void Set<TElement>::sterge(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
if (table[pozitie] == NULL)
return;
if (table[pozitie]->element == element)
{
Nod* deSters = table[pozitie];
table[pozitie] = table[pozitie]->next;
delete deSters;
dimensiune--;
return;
}
Nod* elem = table[pozitie];
while (elem->next != NULL && (elem->next->element) == element)
elem = elem->next;
if (elem->next != NULL)
{
Nod* deSters = elem->next;
elem->next = elem->next->next;
delete deSters;
dimensiune--;
}
}
template <typename TElement>
bool Set<TElement>::cauta(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
while (curent != NULL && !(element == curent->element))
curent = curent->next;
if (curent != NULL)
{
return true;
}
return false;
}
template<typename TElement>
class IteratorSet {
public:
IteratorSet(Set<TElement>* m);
void next();
bool valid();
TElement element();
private:
Set<TElement>* Set;
typename Set<TElement>::Nod* crt;
};
template<typename TElement>
IteratorSet<TElement>::IteratorSet(Set<TElement>* mul) {
Set = mul;
crt = mul->prim;
}
template<typename TElement>
bool IteratorSet<TElement>::valid() {
return crt != NULL;
}
template<typename TElement>
TElement IteratorSet<TElement>::element() {
return crt->element;
}
template<typename TElement>
void IteratorSet<TElement>::next() {
crt = crt->next;
}
=======================================================
domain.h (names of Pizzas)
#include <string>
using namespace std;
class Pizza {
public:
Pizza(string namePizza) : namePizza(namePizza) {}
Pizza() : namePizza("") {}
string getName() const {
return namePizza;
}
int hashCode()
{
int sum = 0;
for (unsigned i = 0; i < str.length(); i++)
sum += str[i];
return sum;
}
bool operator == (Pizza& other) {
return namePizza == other.getName();
}
private:
string namePizza;
string str;
};
====================================================
main.cpp:
#include "SetADT.h"
#include <string>
#include <iostream>
#include "domain.h"
void show(Set<Pizza>* set) {
IteratorSet<string> it = set->iterator();
while (it.valid()) {
cout << "\t" << it.element().getName() << endl;
it.next();
}
}
int main()
{
Set<Pizza> set;
Pizza pizza1{ "diavola" };
Pizza pizza2{ "prosciuto" };
set.add(pizza1);
set.add(pizza2);
show(set);
return 0;
}
When I try to print the objects added to the Set it pops and error and the program stops.
I don't know anywhere else to look to find the problem.
Anyway, if the code sample isn't enough, here the complete project ( has parts of romanian in it )
http://www20.zippyshare.com/v/qKpEcZhr/file.html
The reason might be, for example, prim variable that you use in the iterator, that is initialized to an undefined value. However, code you posted is not compilable, i.e. there are other problems why your code is not working. Did not download your zip file.
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.
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.