Changing an array class to hold a dynamic array - c++

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;
}
}

Related

Circular Queue Bug Fix + Improvement Critiques

The issue is portrayed clearly in the display function.I wanted to display the array items in top, but I couldn't figure out a way to do so as it was constantly being incremented.
Instead of this...:
void CircularQueue :: Display() const {
for(int i = front; i < MAX; i++) {
cout << a[i] << endl;
}
}
**I want to display the circular queue using top:**
void CircularQueue :: Display() const {
for(int i = front; i < top; i++) {
cout << a[i] << endl;
}
}
In my main function, I enqueue'd 15 items, and as a result, top incremented 15 times. So obviously there would be 5 garbage values. How can I manipulate top so that the display function shows all 10 array values?
#include <iostream>
using namespace std;
#define MAX 10
class CircularQueue {
private:
int top;
int front;
public:
//assume that the max number of items in this circular queue is 10.
int a[MAX];
CircularQueue() {top = -1; front = -1;}
int enqueue(int x);
void dequeue();
void peekFront() const;
void peekBack() const;
void Display() const;
bool isEmpty();
};
//1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
//10,11,12,13,14,15,6,7,8,9
int CircularQueue :: enqueue(int x) {
//Problem: The array is actually growing in size.
++top;
a[top%10] = x;
int y = a[top%10];
cout << "Adding " << y << " to the queue." << endl;
if(top == 0) {
front = 0;
}
return y;
}
void CircularQueue :: dequeue() {
if(top < 0) {
cout << "The queue is empty." << endl;
} else {
int x = a[top];
cout << x << " will now be removed." << endl;
for(int i = 0; i <= top - 1; i++) {
a[i] = a[i+1];
}
top--;
x = a[top];
cout << "The last element of the queue is now: " << x << endl;
}
}
bool CircularQueue :: isEmpty() {
return top < 0;
}
void CircularQueue :: peekFront() const {
if(front < 0) {
cout << "The queue is empty." << endl;
} else {
int x = a[front];
cout << "The Front value is: " << x << endl;
}
}
void CircularQueue :: peekBack() const {
if(top < 0) {
cout << "The queue is empty." << endl;
} else {
int x;
x = a[top];
cout << "The back value is: " << a[top] << endl;
}
}
void CircularQueue :: Display() const {
for(int i = front; i < MAX; i++) {
cout << a[i] << endl;
}
}
int main() {
CircularQueue Aq;
Aq.enqueue(0);
Aq.enqueue(1);
Aq.enqueue(2);
Aq.enqueue(3);
Aq.enqueue(4);
Aq.enqueue(5);
Aq.enqueue(6);
Aq.enqueue(7);
Aq.enqueue(8);
Aq.enqueue(9); Aq.Display();
Aq.enqueue(10);
Aq.enqueue(11);
Aq.enqueue(12);
Aq.enqueue(13);
Aq.enqueue(14);
Aq.enqueue(15); Aq.Display();
return 0;
}
Expected output should be:
10,11,12,13,14,15,6,7,8,9
The array size should be 10 always. But when I keep enqueueing; The array size goes beyond 10.

Debug Assertion Fails On Dynamic Array

So here is my working code for a simple dynamic array. This has to be a sample code for a very entry level data structure implementation:
#include <iostream>
using namespace std;
class AdvancedArray {
public:
AdvancedArray();
~AdvancedArray();
int get_size() const; // get the number of elements stored
double& at(int idx) const; // access the element at idx
void push_back(double d); // adds a new element
void remove(int idx); // remove the element at idx
void clear(); // delete all the data stored
void print() const;
private:
double* elements;
int size;
};
int main()
{
AdvancedArray* arr = new AdvancedArray();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "Pusing Values: 1.2, 2.1, 3.3, 4.5 in the Array. " << endl;
arr->push_back(1.2);
arr->push_back(2.1);
arr->push_back(3.3);
arr->push_back(4.5);
arr->print();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "The Element at Index 2 is: " << arr->at(2) << endl;
cout << "Deleting Values: 2.1 from the Array. " << endl;
arr->remove(1);
cout << "The Array Size is: " << arr->get_size() << endl;
arr->print();
cout << "Clearing the Array: " << endl;
arr->clear();
cout << "The Array Size is: " << arr->get_size() << endl;
arr->clear();
return 0;
}
AdvancedArray::AdvancedArray()
{
size = -1;
elements = new double[100]; //Maximum Size of the Array
}
AdvancedArray::~AdvancedArray()
{
delete[] elements;
}
int AdvancedArray::get_size() const
{
if(size < 0)
{
return 0;
}
return size;
}
double & AdvancedArray::at(int idx) const
{
if (idx < 100 && idx >= 0 && size > 0) {
return elements[idx];
}
cout << "Index Out of Bounds." << endl;
}
void AdvancedArray::push_back(double d)
{
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
}
void AdvancedArray::remove(int idx)
{
if (size >= 100 || size < 0)
{
cout << "No Such Element Exists!" << endl;
}
else
{
for(int i = idx; i <size; i++)
{
elements[idx] = elements[idx + 1];
}
size--;
cout << "Element Deleted In Stack Successfully!" << endl;
}
}
void AdvancedArray::clear()
{
delete[] elements;
size = -1;
}
void AdvancedArray::print() const
{
cout << "[ ";
for(int i = 0; i <= size; i++)
{
cout << elements[i] << " ";
}
cout << "]" << endl;
}
So every time I try to run this I have the 2 problems:
What is wrong with my code? Why is the heap getting corrupted (I searched about the error code and that's all has to say)? Is my code doing some major access violations? I am using VS2015.
You do delete [] elements three times without setting elements to nullptr in between. That leads to undefined behavior the second time (and third) time.
When size == 99, the following piece of code attempts to access elements[100]:
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
You need to change ++size to size++.

C++ Hamming Function

This program is supposed to create three arrays of class object My_array. The first array is filled with random numbers. The second array is an exact copy of the first. The third array is entered by the user. The program checks to make sure that the first two arrays indeed equal each other and then it check to the hamming distance of the first and third array. The professor defines the hamming distance as each part off the array that is different.
My problem has been getting hamming to work. I actually have a hard time with operating overloading so I am surprised that works (well I have no errors showing in VS Studio) but not the hamming part. Any help would be appreciated. There are three files in order: main.cpp, my_array.cpp, and my_array.h. Function definitions and declarations were provided by professor. I am required to insert how each function operates.
#include "my_array.h"
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "How big of an array shall we work with? ";
cin >> size;
My_array a(size);
My_array b(size);
My_array c(size);
a.randomize(100);
b = a;
c.input();
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << "a != b: " << (a != b) << endl;
cout << "a == b: " << (a == b) << endl;
cout << "The hamming distance is: " << a.hamming(c);
return 0;
}
#include "my_array.h"
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <time.h>
// Constructor
My_array::My_array(int the_size)
{
array = NULL;
size = 0;
resize(the_size);
}
// Destructor.
My_array::~My_array()
{
empty();
}
// Copy constructor
My_array::My_array(My_array &data)
: size(data.size)
{
array = new int[size];
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
// Overloaded assignment operator.
My_array &My_array::operator=(My_array &data)
{
if (this != &data) {
resize(data.size);
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
else
cout << "Attempt to copy an object on itself. "
<< "Operation ignored." << endl;
return *this;
}
void My_array::input()
{
int j;
cout << "Please enter " << size << " numbers.\n";
for (int i = 0; i < size; i++)
{
cout << "Number " << i + 1 << ": ";
cin >> j;
array[i] = j;
}
}
void My_array::randomize(int limit)
{
srand(time(NULL));
for (int i = 0; i < size; i++)
array[i] = rand() % limit + 1;
}
bool My_array::operator ==(My_array &data)
{
if(this->size != data.size)
return false;
for (int i = 0; i <size; i++)
{
if (*this[i].array != data.array[i])
return false;
}
return true;
}
bool My_array::operator !=(My_array &data)
{
if (*this == data)
return false;
return true;
}
int My_array::hamming(My_array &data)
{
int ham = 0;
for (int i = 0; i < size; i++)
if (*this[i].array != data[i].array)
ham++;
return ham;
}
// This function will empty the target object
void My_array::empty()
{
if (size != 0 && array != NULL) {
size = 0;
delete[] array;
}
}
// Resize the array.
void My_array::resize(int the_size)
{
if (size >= 0) {
empty();
if (the_size != 0) {
size = the_size;
array = new int[size];
}
}
else
cout << "Resize attepmted with a negative size. "
<< "Operation ignored." << endl;
}
// Access an element of the array.
int &My_array::operator[](int index)
{
if (index < size)
return array[index];
else {
cerr << "Illegal access to an element of the array." << endl
<< "The size of the array was " << size
<< " and the index was " << index << endl;
exit(1);
}
}
// Accessor
int My_array::get_size()
{
return size;
}
void My_array::output()
{
cout << "The array of size " << size
<< " contains the elements:" << endl;
for (int i = 0; i<size; i++)
cout << array[i] << ' ';
cout << endl;
}
//overloading the << operator.
ostream &operator<<(ostream &out, My_array &data)
{
out << "The array of size " << data.size
<< " contains the elements:" << endl;
for (int i = 0; i<data.size; i++)
out << data.array[i] << ' ';
out << endl;
return out;
}
#ifndef MY_ARRAY_H
#define MY_ARRAY_H
#include <iostream>
using namespace std;
class My_array {
protected:
int size;
int *array;
public:
// Constructor
My_array(int the_size = 0);
// Destructor
~My_array();
// Copy constructor
My_array(My_array &data);
// Assignment operator
My_array &operator=(My_array &data);
void input();
void randomize(int limit);
bool operator ==(My_array &data);
bool operator !=(My_array &data);
int hamming(My_array &data);
// Deletes the array
void empty();
// Resize the array.
void resize(int the_size = 0);
// Access an element of the array.
int &operator[](int index);
// Returns the size of the array.
int get_size();
// Output the elements of the array.
void output();
friend ostream &operator<<(ostream &out, My_array &data);
};
#endif
This:
*this[i].array != data[i].array
should be this:
array[i] != data.array[i]
or this:
array[i] != data[i]
The *this is unnecessary, and data[i] is a reference to an int (the same one you get by calling data.array[i], thanks to your operator[]), and an int has no member called "array".

Errors within Main program using classes

I just have a few errors of the same type in my main program. My college professor is not answering my emails so I have to resort to asking you guys. In my main program I have several errors somewhat similar to this: "request for member which is of non-class type." Program01 is basically testing every function in ListType.h, OListType.h, and UListType.h to make sure everything works correctly. Any help you can provide in a timely fashion will be appreciated.
Here is ListType.h:
#ifndef LISTTYPE_H_INCLUDED
#define LISTTYPE_H_INCLUDED
#include <iostream>
class ListType {
public:
ListType(size_t=10);
ListType(const ListType&);
virtual ~ListType();
virtual bool insert(int)=0;
virtual bool eraseAll();
virtual bool erase(int)=0;
virtual bool find(int) const=0;
size_t size() const;
bool empty() const;
bool full() const;
friend std::ostream& operator << (std::ostream&, const ListType&);
const ListType& operator= (const ListType&);
protected:
int *items;
size_t capacity;
size_t count;
};
#endif // LISTTYPE_H_INCLUDED
Here is ListType.cpp:
#include "ListType.h"
ListType::ListType (size_t a) {
capacity = a;
count = 0;
items = new int [capacity];
}
ListType::ListType(const ListType& newlist) {
capacity = newlist.capacity;
count = newlist.count;
items = new int [capacity];
for (size_t i = 0; i < count; ++i)
items[i] = newlist.items[i];
}
ListType::~ListType() {
delete [] items;
}
bool ListType::eraseAll() {
count = 0;
return 0;
}
size_t ListType::size() const {
return (count);
}
bool ListType::empty() const {
return (count == 0);
}
bool ListType::full() const {
return (count == capacity);
}
std::ostream& operator << (std::ostream& out, const ListType& my_list) {
if (!my_list.empty()) {
for (size_t i = 0; i < my_list.count; ++i){
out << my_list.items[i] << ',';
}
}
return out;
}
const ListType& ListType::operator= (const ListType& rightObject) {
if (this != & rightObject) {
delete [] items;
capacity = rightObject.capacity;
count = rightObject.count;
items = new int[capacity];
for (size_t i = 0; i < count; ++i) {
items[i] = rightObject.items[i];
}
}
return *this;
}
Here is UListType.h:
#ifndef ULISTTYPE_H_INCLUDED
#define ULISTTYPE_H_INCLUDED
#include <iostream>
class UListType: public ListType {
public:
UListType(size_t=10);
bool insert(int);
bool erase(int);
bool find(int) const;
};
#endif // ULISTTYPE_H_INCLUDED
Here is UListType.cpp:
#include "ListType.h"
#include "UListType.h"
UListType::UListType (size_t c): ListType(c) {}
bool UListType::insert(int item) {
if (full()) {
int *newitems;
capacity *=2;
newitems = new int[capacity];
for (size_t i =0; i < count; ++i){
newitems[i] = items[i];
}
delete [] items;
items = newitems;
}
items[count++] = item;
return true;
}
bool UListType::erase(int item) {
bool result = false;
size_t i=0;
while ( i < count && items [i] != item) {
++i;
}
if (i < count) {
items[i] = items[-- count];
result = true;
}
return result;
}
bool UListType::find(int item) const {
size_t i = 0;
while (i < count && items [i] != item) {
++i;
}
return i < count;
}
Here is OListType.h:
#ifndef OLISTTYPE_H_INCLUDED
#define OLISTTYPE_H_INCLUDED
#include <iostream>
class OListType: public ListType {
public:
OListType(size_t=10);
bool insert(int);
bool erase(int);
bool find(int) const;
};
#endif // OLISTTYPE_H_INCLUDED
Here is OListType.cpp:
#include "ListType.h"
#include "OListType.h"
OListType::OListType(size_t c): ListType(c) {}
bool OListType::insert(int item) {
size_t i = count;
if (full()) {
int *newitems;
capacity *=2;
newitems = new int[capacity];
for(size_t j=0; j < count; ++j) {
newitems[j] = items[i];
}
delete [] items;
items = newitems;
}
while (i > 0 && items[i-1] > item){
items[count++] = item;
}
return true;
}
bool OListType::erase(int item) {
bool found=false;
size_t i=0, j= count-1, mid;
while (i <= j && !(found)){
mid = (i + j)/2;
if (item < items [mid])
j = mid - 1;
else if (item > items [mid])
i = mid + 1;
found = items [mid] == item;
}
if (found) {
for (i = mid; i < count - 1; ++i) {
items [i] = items [i +1];
}
--count;
}
return found;
}
bool OListType::find (int item) const {
bool found=false;
size_t i=0, j= count-1, mid;
while (i <= j && !(found)){
mid = (i + j)/2;
if (item < items [mid])
j = mid - 1;
else if (item > items [mid])
i = mid + 1;
found = items [mid] == item;
}
return found;
}
Here is Program01.cpp:
#include "ListType.h"
#include "UListType.h"
#include "OListType.h"
#include <iostream>
using namespace std;
int main() {
OListType list[5] = {165, 16, 118, 212, 104};
UListType ranlist[10] = {243, 300, 154, 153, 592, 124, 195, 217, 289, 405};
UListType UListAssignmentTest;
OListType OListAssignmentTest;
cout << "The Ordered List before operations:" << endl;
cout << list << endl << endl;
if(list.empty()) **<-- HERE BE THE ERROR**
cout << "The list is empty, therefore it is true.";
else
cout << "The list is full or partially full, therefore it is false";
cout << endl << endl;
if(list.full())
cout << "The list is full, therefore it is true.";
else
cout << "The list is partially full or empty, therefore it is false";
cout << endl << endl;
list.insert(25);
cout << endl << endl;
cout << "The Ordered list after Insert:" << endl;
cout << list << endl << endl;
list.find(25);
cout << endl << endl;
list.find(30);
cout << endl << endl;
list.erase(25);
cout << endl << endl;
cout << "The Ordered List after Erase:" << endl;
cout << list << endl << endl;
cout << "The Unordered List before operations:" << endl;
cout << ranlist << endl << endl;
if(ranlist.empty())
cout << "The list is empty, therefore it is true.";
else
cout << "The list is full or partially full, therefore it is false";
cout << endl << endl;
if(ranlist.full())
cout << "The list is full, therefore it is true.";
else
cout << "The list is partially full or empty, therefore it is false";
cout << endl << endl;
ranlist.insert(25);
cout << endl << endl;
cout << "The Unordered List after Insert:" << endl;
cout << ranlist << endl << endl;
ranlist.find(25);
cout << endl << endl;
ranlist.find(30);
cout << endl << endl;
ranlist.erase(25);
cout << endl << endl;
cout << "The Unordered List after Erase:" << endl;
cout << ranlist << endl << endl;
cout << "Testing Ordered List Assignment Operator" << endl;
OListAssignmentTest = list;
cout << OListAssignmentTest << endl << endl;
cout << "Testing Unordered List Assignment Operator" << endl;
UListAssignmentTest = ranlist;
cout << UListAssignmentTest << endl << endl
cout << "Testing Ordered List Copy Constructor" << endl;
OListType OListVariable = list;
cout << OListVariable << endl << endl;
cout << "Testing Unordered List Copy Constructor" << endl;
UListType UListVariable = ranlist;
cout << UListVariable << endl << endl;
cout << "Testing Erase All for OList" << endl;
list.eraseAll();
cout << "OList values now: " << list.empty() << endl << endl;
cout << "Testing Erase All for UList" << endl;
ranlist.eraseAll();
cout << endl << "UList values now: " << ranlist.empty() << endl;
return 0;
}
OListType list[5] = {165, 16, 118, 212, 104};
This line declares an array of 5 OListType types. This doesn't seem correct.
You want to declare one OLIstType and insert 5 values into it. If not, please clarify what that line is supposed to denote.
Here is probably what you are supposed to do:
OListType list;
list.insert(165);
list.insert(16); // etc...

C++ Heap Corruption in Template array

As the title already says, I have a problem with a heap corruption in my C++ code.
I know there are a lot of topics that cover heap corruption problems, and I have visited a lot of them, I read up on a lot of sites about these matters and I've even used Visual Leak Detector to find the location of the memory leak. I still can't seem to figure out why I have a heap corruption.
My code:
#include <iostream>
#include "stdafx.h"
#include "cstdlib"
#include <vld.h>
#include <math.h>
using namespace std;
template <class T>
class PrioQueue
{
private:
int size_;
int tempIndex;
public:
T *bottom_;
T *top_;
PrioQueue(int n =20){
size_ = n;
bottom_ = new T[size_];
top_ = bottom_;
}
void push(T c){
//add the item to the list
*top_ = c;
top_++;
//Save the old stack values in the temp memory
T* values = bottom_;
T tempItem;
int index = num_items();
cout << "Num items: " << index << endl;
cout << "1" << endl;
while(index > 1){
cout << "2" << endl;
if(values[index-1] > values[index-2])
{
cout << "2b" << endl;
tempItem = values[index-2];
values[index-2] = c;
values[index-1] = tempItem;
}
cout << "3" << endl;
index--;
}
cout << "4" << endl;
}
// + operator
PrioQueue* operator+ (PrioQueue que2)
{
PrioQueue<T>* temp = new PrioQueue<T>();
cout << "Created temporary queue" << endl;
for(int i = 0; i <num_items(); i++)
{
cout << "Element in list: " << bottom_[i] << endl;
temp->push(bottom_[i]);
cout << "Temp is now: ";
temp->print();
}
for(int i = 0; i < que2.num_items(); i++)
{
cout << "Element in list: " << que2.bottom_[i] << endl;
temp->push(que2.bottom_[i]);
cout << "Temp is now: ";
temp->print();
}
cout << "Ran loop" << endl;
return temp;
}
// * operator
PrioQueue* operator* (PrioQueue que2)
{
PrioQueue<T>* temp = new PrioQueue<T>();
for(int i = 0; i < num_items(); i++)
{
for(int j = 0; j < que2.num_items(); j++)
{
if(bottom_[i] == que2.bottom_[j])
{
temp->push(bottom_[i]);
break;
}
}
}
return temp;
}
friend ostream& operator<< (ostream& output, PrioQueue& q) {
for(T *element = q.bottom_; element < q.top_; element++)
output << *element << " | ";
return output;
}
int num_items() {
return (top_ - bottom_ );
}
T pop(){
top_--;
return *top_;
}
int full() {
return (num_items() >= size_);
}
int empty() {
return (num_items() <= 0);
}
void print(){
cout << "Print function..." << endl;
cout << "Stack currently holds " << num_items() << " items: " ;
for (T *element=bottom_; element<top_; element++) {
cout << " " << *element;
}
cout << "\n";
}
~PrioQueue(){ // stacks when exiting functions
delete [] bottom_;
}
};
int main()
{
PrioQueue<int> *p1 = new PrioQueue<int>(20);
p1->push(5);
p1->push(2);
p1->push(8);
p1->push(4);
p1->print(); cout << "\n";
PrioQueue<int> *p2 = new PrioQueue<int>(5);
p2->push(33);
p2->push(66);
p2->push(8);
p2->push(5);
p2->print(); cout << "\n";
//add them together
p1->print();
p2->print();
((*p1) + (*p2))->print();
((*p1) * (*p2))->print();
PrioQueue<float> *f1 = new PrioQueue<float>(5);
f1->push(1.1f);
f1->push(5.2f);
f1->push(8.3f);
f1->push(14.4f);
f1->push(17.5f);
f1->print(); cout << "\n";
PrioQueue<float> *f2 = new PrioQueue<float>(4);
f2->push(2.2f);
f2->push(6.7f);
f2->push(10.3f);
f2->push(15.6f);
f2->print();
cout << "\n";
//add them together
((*f1) + (*f2))->print();
// Multiply them.
((*f1) * (*f2))->print();
cout << "\n";
cout << p1 << endl;
cout << f1 << endl;
cout << "Press any key to exit...";
cin.get();
cin.get();
delete p1;
delete p2;
delete f1;
delete f2;
return 0;
}
I already tried removing everything and start at the beginning.
It seemed that changing:
delete [] bottom_;
To:
delete bottom_;
Fixed it, but that was before I pushed a value to the array.
Could some of you please enlighten me on what is wrong. It would be very much appreciated.
Thank you in advance,
Greatings Matti Groot.
The change you mention leads to undefined behavior. If you got something with new[] you must pass it to delete[]. Plain delete is only good for what you got with plain new.
Your operator + and * creates new objects and return pointer to it. I don't see any attempt to delete those objects, so no wonder you have leaks. (It counts as bad design to return pointers-with-obligation for no good reason, even more so from operators on objects that should produce objects.)
1. Stop using new everywhere.
If you want a new Object to work with, create one on the stack.
PrioQueue *p1 = new PrioQueue(20); // NO!
PrioQueue q1(20); // YES!
2. Consider to use unsigned values where usigned values are appropriate.
3. In your operator+() you'll have to set the size of the new temporary Queue appropriately.
4. See Blastfurnace's answer regarding resource managment and operator design.
5. Try to find out what resource acquisition is initialization (RAII) is and use this knowledge.
I addressed some of your issues
template <class T>
class PrioQueue
{
private:
size_t size_;
T *bottom_;
T *top_;
public:
PrioQueue (void)
: size_(20U), bottom_(new T[20U]), top_(bottom_)
{
}
PrioQueue(size_t n)
: size_(n), bottom_(new T[n]), top_(bottom_)
{
}
PrioQueue(PrioQueue<T> const & rhs)
: size_(rhs.size_), bottom_(new T[rhs.size_]), top_(bottom_)
{
for (size_t i=0; i<size_; ++i)
{
bottom_[i] = rhs.bottom_[i];
}
}
PrioQueue<T> & operator= (PrioQueue<T> rhs)
{
swap(rhs);
}
void push (T c)
{
// check if its full
if (full()) throw std::logic_error("full");
//add the item to the list
*top_ = c;
top_++;
// there is no point operating on a new pointer named "values" here
// your still addressing the same memory, so you can just operate on bottom_ instead
for (size_t index = num_items()-1; index > 0; --index)
{
if(bottom_[index] > bottom_[index-1])
{
std::swap(bottom_[index], bottom_[index-1]);
}
}
}
// + operator
PrioQueue<T> operator+ (PrioQueue<T> const & que2)
{
// you need a temporary queue that is large enough
// so give it the proper size (sum of both sizes)
PrioQueue<T> temp(num_items() + que2.num_items());
std::cout << "Created temporary queue" << std::endl;
for(size_t i = 0; i <num_items(); i++)
{
std::cout << "Element in list: " << bottom_[i] << std::endl;
temp.push(bottom_[i]);
std::cout << "Temp is now: ";
temp.print();
}
for(size_t i = 0; i < que2.num_items(); i++)
{
std::cout << "Element in list: " << que2.bottom_[i] << std::endl;
temp.push(que2.bottom_[i]);
std::cout << "Temp is now: ";
temp.print();
}
std::cout << "Ran loop" << std::endl;
return temp;
}
// * operator
PrioQueue<T> operator* (PrioQueue<T> const & que2)
{
size_t que1_items = num_items(), que2_items = que2.num_items();
PrioQueue<T> temp(que1_items);
for (size_t i = 0U; i < que1_items; ++i)
{
for(size_t j = 0U; j < que2_items; ++j)
{
if(bottom_[i] == que2.bottom_[j])
{
temp.push(bottom_[i]);
}
}
}
return temp;
}
friend std::ostream& operator<< (std::ostream& output, PrioQueue<T> & q)
{
for(T *element = q.bottom_; element < q.top_; element++)
output << *element << " | ";
return output;
}
size_t num_items(void) const
{
return size_t(top_ - bottom_ );
}
T pop (void)
{
// you actually popped of the last element and returned the next
// i think it is likely you want to return the element you pop off
return *(top_--);
}
// why int? full or not is a rather boolean thing i guess
bool full (void) const
{
// num_items() > size_ must not happen!
return (num_items() == size_);
}
bool empty(void) const
{
// an unsigned type cannot be < 0
return (num_items() == 0);
}
void swap (PrioQueue<T> & rhs)
{
std::swap(size_, rhs.size_);
std::swap(bottom_, rhs.bottom_);
std::swap(top_, rhs.top_);
}
void print (void) const
{
cout << "Print function..." << endl;
cout << "Stack currently holds " << num_items() << " items: " ;
for (T * element=bottom_; element<top_; ++element)
{
cout << " " << *element;
}
cout << endl;
}
~PrioQueue()
{
delete [] bottom_;
}
};
int main()
{
PrioQueue<int> q1;
q1.push(5);
q1.push(2);
q1.push(8);
q1.push(4);
q1.print();
PrioQueue<int> q2;
q2.push(33);
q2.push(66);
q2.push(8);
q2.push(5);
q2.print();
std::cout << "Plus: " << std::endl;
PrioQueue<int> q_plus = q1+q2;
q_plus.print();
std::cout << "Multi: " << std::endl;
PrioQueue<int> q_multi = q1*q2;
q_multi.print();
}
Your class manages a resource (memory) but you don't correctly
handle copying or assignment. Please see: What is The Rule of
Three?.
The design of your operator+() and operator*() is unusual and
leaks memory. Returning PrioQueue* makes it cumbersome or
impossible to properly free temporary objects. Please see: Operator
overloading
You might be interested in The Definitive C++ Book Guide and List to learn the language basics and some good practices.
I suggest you try re-writing this without using new or delete. Change your * and + operators to return a PrioQueue. Change the PrioQueue to use a vector<T> instead of an array. You can then focus on writing your own priority queue. Make sure you use the standard priority queue if you actually need one though.
((*p1) + (*p2))->print();
and statements like these .. Your + & * operator returns a new'ed PrioQueue . So you are not deleting it anywhere .
So try to take return value in a temp PrioQueue pointer and call delete on it as well .