Testing for Equivalency of Dynamic Arrays (no std::vector!) - c++

I am currently working with dynamic arrays without the use of vector. The program completes different actions on the array class object through a menu. All of the actions seem to work except when testing for equivalency after I copy the first dynamic array (stack1) to a second dynamic array (stack2) of the same capacity. In this scenario, it will state that the two stacks are equivalent even though they are not. For example, the console will output the following when stack 1 is empty and stack 2 contains elements:
I am unsure if this is a problem with my equality operator or assignment operator. My .h file, .cpp file, and main driver file are included below.
h file:
#include <iostream>
class DoubleStack
{
public:
DoubleStack(size_t capacity); //Constructor
DoubleStack(const DoubleStack& rhs); //Copy Cosntructor
~DoubleStack(void); //Destructor
DoubleStack& operator=(DoubleStack& rhs); //Assignment operator overload
int push(double& item); //Add double to top of stack
int pop(double& item); //Remove top double from stack
int empty(void); //Check to see if stack is empty
size_t capacity(void); //Check capacity of stack
size_t size(void); //Check number of elements on stack
int operator==(DoubleStack& rhs); //Comparison operator for two stacks
friend std::ostream& operator<< (std::ostream &output, const DoubleStack& s); //Operator overload for ostream <<
private:
double *data; //pointer for dynamic stack
size_t stack_size; //Capacity of the stack
size_t tos; //Top of stack. 0 == empty stack
size_t noi; //Number of elements on stack
.cpp file:
#include <iostream>
#include "dblstk.h"
//Constructor & Copy Constructor
DoubleStack::DoubleStack(size_t capacity)
{
data = new double[capacity]();
stack_size = capacity;
tos = 0;
noi = 0;
}
DoubleStack::DoubleStack(const DoubleStack& rhs)
{
data = rhs.data;
stack_size = rhs.stack_size;
tos = rhs.tos;
noi = rhs.noi;
}
//Destructor
DoubleStack::~DoubleStack(void)
{
delete[] data;
}
//Overload for comparison operator
int DoubleStack::operator==( DoubleStack& rhs)
{
for (int i = 0; i < tos; i++)
{
if (data[i] == rhs.data[i])
{
return true;
}
else
{
return false;
}
}
}
//Assignment operator overload
DoubleStack& DoubleStack::operator=(DoubleStack& rhs)
{
delete[] data;
data = new double[rhs.stack_size];
stack_size = rhs.stack_size;
tos = rhs.tos;
for (int i = 0; i < tos; i++)
{
data[i] = rhs.data[i];
};
return *this;
}
//ostream operator overload
std::ostream& operator<< (std::ostream &output, const DoubleStack& s)
{
for (int i = 0; i<s.tos; i++)
{
if (i > 0)
{
output << ", ";
}
output << s.data[i];
};
return output;
}
//DoubleStack functions
DoubleStack::push(double& item)
{
if (noi >= stack_size)
{
std::cout<<"Stack size at capacity. Cannot push."<<std::endl;
return 0;
}
else
{
noi++;
data[tos++] = item;
std::cout<<"Inserted "<<item<<std::endl;
return 1;
}
}
DoubleStack::pop(double& item)
{
if (DoubleStack::empty() == true)
{
std::cout<<"Cannot remove number because stack is empty."<<std::endl;
return 0;
}
else
{
noi--;
data[tos] = item;
data[tos--];
std::cout<<"Removed "<<data[tos]<<std::endl;
return item;
return 1;
}
}
DoubleStack::empty(void)
{
if (noi == 0)
{
return true;
}
else
{
return false;
}
}
size_t DoubleStack::capacity(void)
{
return stack_size;
}
size_t DoubleStack::size(void)
{
return noi;
}
main file:
#include <iostream>
#include "dblstk.h"
#include "stack_driver.cpp"
//Menu function
void Menu()
{
std::cout<<"-----------------------------------------------------"<<std::endl;
std::cout<<"\t \t Welcome to the Stackhouse. \t \t"<<std::endl;
std::cout<<"-----------------------------------------------------"<<std::endl;
std::cout<<"1. Display Stack 1"<<std::endl;
std::cout<<"2. Place a double value onto the top of stack 1"<<std::endl;
std::cout<<"3. Remove a value from the top of stack 1"<<std::endl;
std::cout<<"4. Check the total capacity of stack 1"<<std::endl;
std::cout<<"5. Check current number of items on stack 1"<<std::endl;
std::cout<<"6. Copy stack 1 to stack 2"<<std::endl;
std::cout<<"7. Check to see if the two stacks are equal"<<std::endl;
std::cout<<"8. Quit"<<std::endl;
std::cout<<"Enter menu selection: "<<std::endl;
}
int main(void)
{
DoubleStack stack1(10);
DoubleStack stack2(10);
Menu();
int user_input;
std::string answer;
do
{
std::cout<<"Select an option (1-8)"<<std::endl;
std::cin>>user_input;
switch (user_input)
{
case 1:
{
std::cout<<"Displaying stack 1:"<<std::endl;
std::cout<<stack1<<std::endl;
break;
}
case 2:
{
std::cout<<"Enter number to push: "<<std::endl;
double push_item;
std::cin>>push_item;
stack1.push(push_item);
break;
}
case 3:
{
std::cout<<"Popped top number from stack."<<std::endl;
double pop_item;
stack1.pop(pop_item);
break;
}
case 4:
{
std::cout<<"The capacity of stack 1 is: "<<stack1.capacity()<<std::endl;
break;
}
case 5:
{
std::cout<<"The current number of items on stack 1 is: "<<stack1.size()<<std::endl;
break;
}
case 6:
{
std::cout<<"Copying stack 1 to stack 2..."<<std::endl;
stack2 = stack1;
std::cout<<"Stack 1 is: "<<stack1<<std::endl;
std::cout<<"Stack 2 is: "<<stack2<<std::endl;
break;
}
case 7:
{
std::cout<<"Checking to see if the two stacks are equal.."<<std::endl;
if (stack1 == stack2)
{
std::cout<<"The stacks are the same!"<<std::endl;
std::cout<<"Stack 1 is: "<<stack1<<std::endl;
std::cout<<"Stack 2 is: "<<stack2<<std::endl;
}
else
{
std::cout<<"The stacks are not the same!"<<std::endl;
std::cout<<"Stack 1 is: "<<stack1<<std::endl;
std::cout<<"Stack 2 is: "<<stack2<<std::endl;
}
break;
}
case 8:
{
std::cout<<"Leaving the Stackhouse. Quitting..."<<std::endl;
return 0;
break;
}
default:
{
std::cout<<"Inavlid."<<std::endl;
break;
}
}
std::cout<<"Press either F/f to continue"<<std::endl;
std::cin>>answer;
}
while (answer == "F" || answer == "f");
}

Your equality operator is bugged. Think about what equality means. Two array are equal if all the items are equal, but they are not equal if any of the items are not equal. But that's not what the code for you equality operator says because you decide whether they are equal or not equal after looking at the first item only.
//Overload for comparison operator
int DoubleStack::operator==( DoubleStack& rhs)
{
for (int i = 0; i < tos; i++)
{
if (data[i] == rhs.data[i])
{
return true;
}
else
{
return false;
}
}
}
Here's a partly fixed version
//Overload for comparison operator
int DoubleStack::operator==( DoubleStack& rhs)
{
for (int i = 0; i < tos; i++)
{
if (data[i] != rhs.data[i])
{
return false;
}
}
return true;
}
See the difference. As soon as I find one not equal number I return false, but I don't return true until I've checked all the numbers.
There is one other fix needed. Two arrays are never equal if their sizes are different. Here's version that checks for that as well.
//Overload for comparison operator
int DoubleStack::operator==( DoubleStack& rhs)
{
// check if same size
if (size() != rhs.size())
return false;
for (int i = 0; i < tos; i++)
{
if (data[i] != rhs.data[i])
{
return false;
}
}
return true;
}
EDIT
Here's another bug.
//Assignment operator overload
DoubleStack& DoubleStack::operator=(DoubleStack& rhs)
{
delete[] data;
data = new double[rhs.stack_size];
stack_size = rhs.stack_size;
tos = rhs.tos;
for (int i = 0; i < tos; i++)
{
data[i] = rhs.data[i];
};
return *this;
}
This assignment operator fails to copy the noi value. It should be
DoubleStack& DoubleStack::operator=(DoubleStack& rhs)
{
delete[] data;
data = new double[rhs.stack_size];
stack_size = rhs.stack_size;
tos = rhs.tos;
noi = rhs.noi; ///////// new line ere
for (int i = 0; i < tos; i++)
{
data[i] = rhs.data[i];
};
return *this;
}
Now the operator== should work as well (because it uses noi to compare sizes).
But think about this. Since in your code tos and noi always have the same value, what is the point of having both? It's just leads to possible bugs. You should eliminate one of them.

Related

Class Dynamic Array Bug

I am required to implement a dynamic array that adjusts, dynamically, in accordance with the number of value (temperatures) that are input into the code. I have written the majority of the code for this to be possible, however I have run into a bug and for the life of me, have been unable to locate the issue.
The program is supposed to output the values of temp_a, make temp_b = temp_a, output the value of temp_b, and then clear the value of temp_a, and finally output the values of temp_b once more.
However, when I compile the program, it outputs that the list is full and cannot add any more values, meaning there is a logic error somewhere in the code.
Please forgive me for the lengthy code, as soon as I can locate the error, the code shall be separated into multiple compilations.
#include <iostream>
using namespace std;
class TemperatureList {
private:
int* temp; // pointer to dynamic array
short current_size; // current number of elements
short max_size; // max number of elements allowed in this list
public:
// Overloading assignment operator
void operator =(const TemperatureList& another_list);
// === Constructors ===
// Default constructor
TemperatureList();
// Constructor that accepts an integer parameter that specifies the max length of the list
TemperatureList(int max);
// Copy constructor that accepts another List as parameter
TemperatureList(const TemperatureList& another_list);
// Destructor
~TemperatureList();
// === Modifier functions ===
// add new_value to end of list if there is still space
void add_temperature(int new_value);
// === Accessor functions ===
// return current current_size of the list
short get_current_size();
// === Other functions ===
// return the last element, or 0 if the list is empty, with a warning output
int get_last();
// return element at the position-th position, or 0 if the list is empty, with a warning output
int get_temp(short position);
// returns if current_size == 0
bool set_temp(short position, int value);
// returns if current_size == 0
bool empty();
// returns if current_size == max_size
bool full();
// Output list separated by commas
friend ostream& operator <<(ostream& outs, const TemperatureList& list);
};
int main() {
TemperatureList temp_a;
temp_a.add_temperature(23.5);
temp_a.add_temperature(24.6);
cout << temp_a;
TemperatureList temp_b = temp_a;
cout << temp_b;
temp_a = TemperatureList();
cout << "Now there's no temperatures in a.\n";
cout << temp_a;
cout << "How about temperatures in b?\n";
cout << temp_b;
return 0;
}
void TemperatureList::operator =(const TemperatureList& another_list) {
delete[] temp;
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::TemperatureList() {
current_size = 0;
max_size = 0;
temp = NULL;
}
TemperatureList::TemperatureList(int max) : max_size(max) {
current_size = 0;
temp = new int[max];
}
TemperatureList::TemperatureList(const TemperatureList& another_list) {
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::~TemperatureList() {
//cout << "== I am in destructor ==\n";
delete[] temp;
}
void TemperatureList::add_temperature(int new_value) {
if (current_size < max_size) {
temp[current_size] = new_value;
current_size++;
}
else {
cout << "Cannot add value to the list. It is full.\n";
}
}
int TemperatureList::get_last() {
if (empty()) {
cout << "The list is empty\n";
return 0;
}
else {
return temp[current_size - 1];
}
}
int TemperatureList::get_temp(short position) {
if (current_size >= position) {
return temp[position - 1];
}
else {
cout << "There is no temperature\n";
return 0;
}
}
bool TemperatureList::set_temp(short position, int value) {
if (current_size >= position) {
temp[position - 1] = value;
return true;
}
else {
return false;
}
}
short TemperatureList::get_current_size() {
return current_size;
}
bool TemperatureList::empty() {
return (current_size == 0);
}
bool TemperatureList::full() {
return (current_size == max_size);
}
ostream& operator <<(ostream& outs, const TemperatureList& list) {
int i;
for (i = 0; i < (list.current_size - 1); i++) {
outs << list.temp[i] << ",";
}
outs << list.temp[i];
return outs;
}
The logic error seems to stem from the fact that you initialize your current_size and max_size to zero. So, unless your run the overloaded constructor (wherein you’re set the max_size), every call to addTemperature() is going to fail the (current_size < max_size) check because they are both equal to zero.

Overloading addition operator (adding a string to an object using a function)

I'm creating a dynamic array class and I'm new to c++. I'm having trouble overloading the addition operator to add a string to an object. When I do try to add a string, nothing shows up on the compile screen. I also added my copy constructor, destructor, overloaded assignment operator, and overloaded ostream operator just in case any of those were the issue. Thank you so much for the help!!
DynamicStringArray::~DynamicStringArray()
{
delete[] dynamic_Array;
dynamic_Array = NULL;
}
DynamicStringArray::DynamicStringArray(const DynamicStringArray& first)
{
size = first.returns_Size();
dynamic_Array = new string[size];
for (int n = 0; n < size; n++)
{
dynamic_Array[n] = first.get_Entry(n);
}
}
void DynamicStringArray::operator =(const DynamicStringArray& first)
{
this->size = first.returns_Size();
this->dynamic_Array = new string[size];
for (int i = 0; i < this->size; i++)
{
this->dynamic_Array[i] = first.get_Entry(i);
}
}
ostream& operator <<(ostream& out, const DynamicStringArray& first) //nonmember requires 2 arguments
{
for (int i = 0; i < first.size; i++)
{
out << first.dynamic_Array[i] << endl;
}
return out;
}
void DynamicStringArray::add_Entry(string a)
{
string* Temp_Array = dynamic_Array; //old array
dynamic_Array = new string[size + 1]; //new array
for (int i= 0; i < size; i++) //copy old string values to temp array
{
dynamic_Array[i] = Temp_Array[i];
}
dynamic_Array[size] = a; //puts string a into last position of new array
delete[]Temp_Array; //free memory space
size++;
}
DynamicStringArray DynamicStringArray::operator +(const string& a)
{
DynamicStringArray added;
added.add_Entry(a);
return added;
}
int main()
{
DynamicStringArray fav_Foods;
fav_Foods.add_Entry("pasta");
fav_Foods.add_Entry("sushi");
fav_Foods + "Burgers";
cout << fav_Foods << endl;
}
DynamicStringArray DynamicStringArray::operator +(const string& a)
{
DynamicStringArray added;
added.add_Entry(a);
return added;
}
Why do you think you need to create a new DynamicStringArray added?
Simply call add_Entry(a) on the current instance. Also, operator+() should return a reference to the instance it is called upon:
DynamicStringArray& DynamicStringArray::operator+(string const &a)
{
add_Entry(a);
return *this;
}

Using object of class as an parametr in method

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

What happens in each scenario and how is this accomplished?

I have a Stack class defined. Now, I want to reverse the stack by passing it to a reverseStack function. I want to know what happens in various scenarios. And finally, what is the best way to do it.
STACK IMPLEMENTATION:
class Stack {
public:
Stack() {
a = new int[25];
capacity = 25;
}
Stack(int size) {
a = new int[size];
capacity = size;
}
~Stack() {
delete[] a;
}
void push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int top();
bool isEmpty();
void flush();
private:
int capacity ;
int* a;
int index = -1; // Index of the top most element
};
SCENARIO-1:
void reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
s = s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
reverseStack(s);
return 0;
}
SCENARIO-2:
Stack reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
return s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
s = reverseStack(s);
return 0;
}
In Scenario-1 (which fails), what does s = s2 inside the function mean? I think it's a member-wise copy. Would it have worked if the data members didn't involve a pointer (int* a)?
Scenario-2 fails as well for the same reason. How do I accomplish what I'm trying to?
Should I have a copy-constructor (and how do I implement it?). How about overloading the assignment operator (again, how do I implement?) ?
I tried to implement it this way:
Stack Stack::operator = (Stack 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;
}
About the scenarios, the best one is the second because of the return value optimization, i.e: The compiler will probably optimize away the copy of the return value and prevent an unnecessary copy.
Now, you are using dynamic memory in your class, which means the default implementation of the copy constructor and assignment operator will not work for you.
Copy constructor, it's almost the same as the assignment operator you write
Stack::Stack(const Stack& s)
: capacity(s.capacity)
, a(new int[capacity])
, index(s.index)
{ // std::copy is just a shortcut, what you're doing is fine too
std::copy(s.a, s.a + capacity, a);
}
The assignment operator you wrote is wrong in two ways:
It should return a Stack object by reference
The parameter should be a const reference
The rest is just ok
Stack& Stack::operator = (const Stack& s) {
capacity = s.capacity;
a = new int[capacity];
for (int i = 0; i < capacity; i++) { // or std::copy
a[i] = s.a[i];
}
index = s.index;
return *this;
}
Update
Tentative implementation of the reverseStack function (without side-effects), assuming index contains the actual number of items in the stack
Stack reverseStack(const Stack& s) {
Stack s2(s.capacity);
for (int i = 0; i < s2.index; ++i) {
s2.a[i] = s2.a[s2.index -i];
}
return s2;
}
Update Thanks to user657267 from pointing out int* a = new int[capacity]; was wrong

c++ valgrind: Conditional jump or move depends on uninitialised value(s) don't know what to initialize

I've been trying to understand what havn't I initialized in this code and I completely(?) understand what is uninitialized but I don't know how to initialize it.
I am getting the error:
==11931== Conditional jump or move depends on uninitialised value(s)
==11931== at 0x804ABA6: Hashtable<int>::put(int, int) (hash_table.h:169)
==11931== by 0x8048F80: test_put() (hash_table_test.cpp:27)
==11931== by 0x804A551: main (hash_table_test.cpp:52)
==11931== Uninitialised value was created by a heap allocation
==11931== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==11931== by 0x804A9AE: Hashtable<int>::Hashtable() (hash_table.h:64)
==11931== by 0x8048F62: test_put() (hash_table_test.cpp:26)
==11931== by 0x804A551: main (hash_table_test.cpp:52)
from the valgrind so apparantly I havn't been initializing correctly the c'tor for Hashtable class:
Hashtable() :
ht_keys(2), ht_size(0), dynamicArray(NULL) {
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i].delete_val = false;
dynamicArray[i].key=0;
dynamicArray[i].default_node = false;
}
}
the dynamic array is of type Node* which it's private fields are:
bool delete_val;
T element;
int key;
bool default_node;
the class Node is inside the class Hashtable.
how can I initialize dynamicArray?
here's the full code:
#include <string>
#include <iostream>
#include "library2.h"
#include <iterator>
using namespace std;
#ifndef HASH_TABLE_HPP_
#define HASH_TABLE_HPP_
#define DIV 2
//type T must have c'tor, operator !=
template<class T>
class Hashtable {
public:
class Node {
public:
Node(const T t) :
delete_val(false), element(t), key(0), default_node(true) {
}
Node(bool v, const Node& n) :
delete_val(v), element(n.element), key(0), default_node(
n.default_node) {
}
Node(const Node& n) :
delete_val(false), element(n.element), key(n.key), default_node(
n.default_node) {
}
Node() :
delete_val(false), key(0), default_node(true) {
}
bool operator==(const Node* n) {
if (n) {
if (element != n->element || default_node != n->default_node) {
return false;
}
return true;
}
return false;
}
bool operator!=(const Node n) {
if (!(*this == n)) {
return false;
}
return true;
}
bool delete_val;
T element;
int key;
bool default_node;
};
Hashtable() :
ht_keys(2), ht_size(0), dynamicArray(NULL) {
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i].delete_val = false;
dynamicArray[i].key=0;
dynamicArray[i].default_node = false;
}
}
//seriously damaged programming...
Hashtable(Node* array, int HT_keys, int HT_size) :
ht_keys(HT_keys), ht_size(HT_size) {
dynamicArray = new Node[ht_keys];
if (array != NULL) {
for (int i = 0; i < ht_keys; i++) {
dynamicArray[i] = array[i];
}
}
}
Hashtable(const Hashtable& ht) {
if (&ht == this) {
return;
}
ht_keys = ht.ht_keys;
ht_size = ht.ht_size;
dynamicArray = new Node[ht_keys];
for (int i = 0; i < ht.ht_keys; i++) {
this->dynamicArray[i] = ht.dynamicArray[i];
}
}
~Hashtable() {
delete[] this->dynamicArray;
}
Hashtable operator=(const Hashtable& ht) {
Hashtable<T> newHT = ht;
return newHT;
}
//Returns true if some value equal to value exists within the hash table.
bool contains(Node n, int i) {
if (i < 0 || i > ht_keys || !n) {
return false;
}
if (i == ht_keys) {
return false;
}
//make sure that n.delete_val is not set as true.
if (dynamicArray[i]->element == n.element
&& !dynamicArray[i]->delete_val) {
return true;
}
if (dynamicArray[i]->delete_val) {
return contains(n, i + 1);
}
return false;
return true;
}
//Returns true if some key equal to key exists within the hash table.
bool containsKey(int i) {
if (i < 0 || i > ht_keys) {
return false;
}
if (dynamicArray[i]->element && !dynamicArray[i]->delete_val) {
return true;
}
return false;
}
//Returns true if some value equal to value exists within the hash table.
bool containsValue(T e) {
return true;
}
//Returns an enumeration of the values contained in the hash table.
int enumeration() {
return ht_size;
}
//Returns the object that contains the value associated with key.
//If key is not in the hash table, a null object is returned.
Node get(int i) {
if (i >= 0) {
return dynamicArray[i % ht_keys];
}
Node n;
return n;
}
//Returns true if the hash table is empty;
//returns false if it contains at least one key.
bool isEmpty() {
if (ht_size) {
return false;
}
return true;
}
//Returns an enumeration of the keys contained in the hash table.
int keys();
//Inserts a key and a value into the hash table.
//Returns false if key isn't already in the hash table;
//returns true if key is already in the hash table.
bool put(T e, int i) {
if (e && i > 0) {
Node n;
n.default_node = false;
n.delete_val = false;
n.key = i;
n.element = e;
//line 168
for (int j = (i % ht_keys); j < ht_keys; j = ((j + 1) % ht_keys)) { //line 169
if (!dynamicArray[j % ht_keys].element
|| dynamicArray[j % ht_keys].delete_val) {
dynamicArray[j % ht_keys] = n;
ht_size++;
return true;
}else if (i == (j + 1) % ht_keys) {
rehash();
return put(e, i);
}
}
return false;
}
return false;
}
bool put_aux(Node n, int i, Node* Array, int HT_keys) {
for (int j = (i % HT_keys); j < HT_keys; j = ((j + 1) % HT_keys)) {
if (!Array[j % HT_keys].element || Array[j % HT_keys].delete_val) {
Array[j % HT_keys] = n;
return true;
} else if (Array[j % HT_keys].element == n.element) {
return true;
}
}
return false;
}
//Increases the size of the hash table and rehashes all of its keys.
void rehash() {
int old_ht_keys = ht_keys;
ht_keys = DIV * ht_keys;
Node* newArray = new Node[ht_keys];
if (ht_keys > DIV) {
for (int j = 0; j < old_ht_keys; j++) {
put_aux(dynamicArray[j],dynamicArray[j].key,newArray,ht_keys);
}
}
delete[] dynamicArray;
dynamicArray = newArray;
}
//Removes key and its value.
//Returns the value associated with key.
//If key is not in the hash table, a null objecht_sizet is returned.
T remove(int i) {
if (i >= 0 && i < ht_keys) {
Node deleted_node(true, dynamicArray[i % ht_keys]);
dynamicArray[i % ht_keys] = deleted_node;
ht_size--;
return deleted_node.element;
}
return NULL;
}
//Returns the number of entries in the hash table.
int size() {
return this->ht_size;
}
private:
int ht_keys;
int ht_size;
Node* dynamicArray;
};
#endif /* HASH_TABLE_HPP_ */
It seems to be complaining about the line !dynamicArray[j % ht_keys].element (on line 163 of the code you posted; this would be a lot easier if the code you posted matched the code valgrind was using; right now the code you posted is several lines shorter than the code valgrind is using).
You never initialize the element member when you allocate the memory in the constructor. You then attempt to use it here in a conditional statement. valgrind correctly warns you of the problem.