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.
Related
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.
I finished some code that prints out how many times a word shows up. However, when I finished and tried to run the code on a different compiler it did not work. Firstly, here is a picture of my code working on my initial file:
But when I used a different compiler (onlinegdb) I get this error:
The thing that confused me the most is; when I try and replicate the file into a new VS Code .cpp file, it does not work. It runs the code but then prints out nothing. When I went into gdb I find this error:
If anyone knows where the segmentation fault/std::length_error are happening at please let me know, and if you have any recommendations that would be great! Also, knowing why I get different results on the same compiler (VS Code) would also be helpful. Here is my code:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
class WordOccurrence
{
public:
WordOccurrence(const string& word="", int num=1)
{
word_ = word;
num_ = num;
}
bool matchWord(const string & compare)
{
if(word_ == compare)
return true;
else
return false;
}
void increment()
{
num_++;
}
string getWord() const
{
return word_;
}
int getNum() const
{
return num_;
}
private:
string word_;
int num_;
};
class WordList
{
public:
friend bool equal(const WordList&, const WordList&);
WordList();
WordList(const WordList &);
~WordList();
WordList operator= (const WordList &);
void addWordFile(WordList w);
void addWord(const string &);
void print();
private:
WordOccurrence *wordArray_;
int size_;
};
WordList::WordList()
{
size_ = 0;
wordArray_ = new WordOccurrence [size_];
}
WordList::WordList (const WordList &neww)
{
size_ = neww.size_;
wordArray_ = new WordOccurrence[size_];
for (int i = 0; i <= (size_ - 1); i++)
wordArray_[i] = neww.wordArray_[i];
}
WordList::~WordList ()
{
delete [] wordArray_;
}
WordList WordList::operator= (WordList const &overload)
{
WordList temp(overload);
swap(wordArray_, temp.wordArray_);
swap(size_, temp.size_);
return *this;
}
void WordList::addWord(const string& word)
{
if(size_ == 0)
{
WordOccurrence *first_array = new WordOccurrence[1];
first_array[0] = word;
delete[] wordArray_;
wordArray_ = first_array;
delete[] first_array;
size_++;
return;
}
//if the word is already in the array, we increase the count of it by 1
for (int i = 0; i < size_; i++)
{
if (wordArray_[i].matchWord(word))
{
wordArray_[i].increment();
return;
}
}
//if it is not in the array already, we need to increase its size and then add the new word to the wordarray.
WordOccurrence *new_array = new WordOccurrence[size_+1];
for (int i = 0; i < size_; i++)
{
new_array[i] = wordArray_[i];
}
new_array[size_] = WordOccurrence(word);
delete[] wordArray_;
size_++;
wordArray_ = new_array;
delete[] new_array;
}
void WordList::print()
{
//to output to a file because when we get a lot of words it's kinda hard to see on just the terminal
ofstream myfile ("output.txt");
WordList sortedList(*this);
//Sorting from smallest to largest
int smallest = wordArray_[0].getNum();
for (int i = 1; i < size_; i++)
{
//stores the smallest value into smallest
if(wordArray_[i].getNum() < smallest)
smallest = wordArray_[i].getNum();
}
int location = 0;
//stores values from start to finish in the new list starting at location sortedList[0]
while(location < size_)
{
for(int i = 0; i < size_; i++)
{
//runs through the new list until it finds a value that is apart of the smallest/rarest words
if(wordArray_[i].getNum() == smallest)
{
sortedList.wordArray_[location] = wordArray_[i];
location++;
}
}
//increases the value of smallest allowing for numbers with greater found values to be sorted
smallest++;
}
//prints out the sorted version of wordarray
for(int i = 0; i < size_; i++)
{
string word = sortedList.wordArray_[i].getWord();
int count = sortedList.wordArray_[i].getNum();
cout << "Word: " << word << " Amount: " << count << endl;
//for longer amounts of text, it was hard to see on a editor so I also have it out to a file.
myfile << "Word: " << word << " Amount: " << count << endl;
}
}
int main()
{
WordList w;
w.addWord("one");
w.addWord("one");
w.addWord("two");
w.addWord("three");
w.addWord("four");
w.addWord("four");
w.addWord("four");
w.addWord("four");
w.addWord("five");
w.addWord("five");
w.addWord("five");
cout << "Sorted list" << endl;
w.print();
}
This is bugged
WordOccurrence *first_array = new WordOccurrence[1];
first_array[0] = word;
delete[] wordArray_;
wordArray_ = first_array;
delete[] first_array;
size_++;
return;
You assign first_array to wordArray_ and then you delete it. This leaves wordArray_ as an invalid pointer. Just remove delete[] first_array;. Two deletes and only one new should have been a clue that something was wrong.
Same bug later on in the same function
WordOccurrence *new_array = new WordOccurrence[size_+1];
for (int i = 0; i < size_; i++)
{
new_array[i] = wordArray_[i];
}
new_array[size_] = WordOccurrence(word);
delete[] wordArray_;
size_++;
wordArray_ = new_array;
delete[] new_array;
delete[] new_array; should not be there.
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 sorry if this is a very basic question, I'm pretty new to C++.
I'm trying to define my own vector class and an iterator for it. However, whenever I overload an operator the value that is returned is always an address.
For instance, the following code prints 0x7fb6dbc000e0 0x7fb6dbc000e0 when I want it to print 1 0
Since I've been messing around with the syntax for a while, some of the operators look a little different, this is just so that you can see a few things I've tried.
test.cc
#include <iostream>
#include "TwoWayVector.cc"
int main(){
TwoWayVector<int> numbers;
numbers.push_back(3);
numbers.push_back(2);
TwoWayVectorIterator<int>* beginning = numbers.begin();
TwoWayVectorIterator<int>* beginning2 = numbers.begin();
cout << beginning==beginning2;
cout << beginning != beginning2;
cout << endl;
return 0;
}
TwoWayVector.cc
using namespace std;
#include "TwoWayVectorIterator.cc"
template <class T> class TwoWayVector{
public:
T* data;
int capacity;
int nextFree;
TwoWayVector(){
capacity = 10;
nextFree = 0;
data = new T[capacity];
}
~TwoWayVector(){
delete data;
}
T& operator[](const int index){
if( index >= capacity || capacity + index < 0){
string number = static_cast<ostringstream*>( &(ostringstream() << index) )->str();
string error = "index " + number + " is out of bounds";
throw error;
}
else if(index < 0){
return data[nextFree+index];
}
return data[index];
}
bool operator==(const TwoWayVector* vector2){
if(capacity != vector2->capacity){
return false;
}
if(nextFree != vector2->nextFree){
return false;
}
for(int i=0; i<nextFree ; i++){
if(data[i] != vector2[i]){
return false;
}
}
return true;
}
//memory leaks?
void push_back(T object){
if(capacity <= nextFree){
capacity = capacity*2;
T* tmp = new T[capacity];
for(int i=0; i<capacity; i++){
tmp[i] = data[i];
}
delete data;
data = tmp;
}
data[nextFree] = object;
nextFree++;
}
T pop_back(){
nextFree--;
T result = data[nextFree];
data[nextFree] = NULL;
return result;
}
int size(){
return nextFree;
}
TwoWayVectorIterator<T>* begin(){
TwoWayVectorIterator<T>* i = new TwoWayVectorIterator<T>(0,this);
return (i);
}
TwoWayVectorIterator<T>* end(){
TwoWayVectorIterator<T>* i = new TwoWayVectorIterator<T>(nextFree,this);
return(i);
}
};
TwoWayVectorIterator.cc
template<typename T> class TwoWayVector;
template <class T> class TwoWayVectorIterator{
public:
TwoWayVector<T>* vector;
int currentPosition;
TwoWayVectorIterator(TwoWayVector<T>& vec){
currentPosition = 0;
vector = vec;
}
TwoWayVectorIterator( int pos , TwoWayVector<T>* vec){
currentPosition = pos;
vector = vec;
}
bool operator==(const TwoWayVectorIterator* vector2){
bool contents, position;
contents = (vector == vector2) ? true : false;
cout << contents << endl;
position =(currentPosition == vector2->currentPosition) ? true : false;
return (contents && position);
}
bool& operator!=(const TwoWayVectorIterator* vector2){
bool contents, position;
contents = (vector == vector2) ? false : true;
position=(currentPosition == vector2->currentPosition) ? false : true;
return (contents || position);
}
TwoWayVectorIterator& operator++(){
return *this;
currentPosition = (currentPosition+1);
}
TwoWayVectorIterator& operator++(int){
currentPosition = (currentPosition+1);
return *this;
}
TwoWayVectorIterator& operator=(TwoWayVectorIterator* vector2){
&vector = vector2;
currentPosition = vector2->currentPosition;
return *this;
}
TwoWayVectorIterator& operator+(int n){
currentPosition = currentPosition+n;
return *this;
}
TwoWayVectorIterator& operator-(int n){
currentPosition = currentPosition-n;
return *this;
}
bool& operator<(TwoWayVectorIterator* vector2){
return (currentPosition<vector2->currentPosition);
}
T& operator*(){
return vector[currentPosition];
}
};
cout << beginning==beginning2;
does not mean
cout << (beginning==beginning2);
It does mean
(cout << beginning) == beginning2;
http://en.cppreference.com/w/cpp/language/operator_precedence
Therefore you are printing a TwoWayVectorIterator<int>*, not a bool.
The precedence of the << operator is higher then the precedence of the == and != operator. So
cout << beginning==beginning2;
cout << beginning != beginning2;
really means
(cout << beginning)==beginning2;
(cout << beginning) != beginning2;
Try
cout << (beginning==beginning2);
cout << (beginning) != beginning2);
I am trying to simulate Conway's game of life using an implementation file I created, I have made good progress but unfortunately I am getting an error which confuses me. I think the problem is ignorance on my part of how to properly code templated functions, anyways this is my implementation file:
#include <list>
#ifndef HashTable_h
#define HashTable_h
using namespace std;
#define HASHTABLE_CAPACITY 1009
template <class DataType>
class HashTable
{
public:
HashTable(); // constructor
bool insert(DataType &a); // insert function for inserting value of dataType into table
bool retrieve(DataType &a); // retrieve function for retrieving value from table
bool replace(DataType &a); // function for replacing the value from the table with the parameter
bool remove(DataType& a);//removed function written and checked
//int getSizeOf() const;
void clear(); // for clearing the table
int size() const;
private:
list<DataType> table[HASHTABLE_CAPACITY]; // static array
int count;
int currentIndex;
typename list<DataType>::const_iterator it;
};
// constructor
template <class DataType>
HashTable<DataType>::HashTable()
{
list<DataType> table[HASHTABLE_CAPACITY];
count = 0;
currentIndex = -1;
}
// retrieve function
template <class DataType>
bool HashTable<DataType>::retrieve(DataType &a)
{
// get wrapped index
int wrappedIndex = a.hashCode() % HASHTABLE_CAPACITY;
if (wrappedIndex < 0) wrappedIndex = wrappedIndex + HASHTABLE_CAPACITY;
// if the array location isn't occupied, fail
if (wrappedIndex < 0 || wrappedIndex >= HASHTABLE_CAPACITY || table[wrappedIndex].empty()) return false;
// iterator for traversing table values
typename list<DataType>::const_iterator it;
// if the keys match then replace the data
// if a collision occurs then return false
it = find(table[wrappedIndex].begin(), table[wrappedIndex].end(), a);
if(it == table[wrappedIndex].end())
return false;
a = *it;
return true;
}
// overloaded operator function
// function for inserting values
template <class DataType>
bool HashTable<DataType>::insert(DataType &value)
{
// get wrapped index
int wrappedIndex = value.hashCode() % HASHTABLE_CAPACITY;
if (wrappedIndex < 0) wrappedIndex = wrappedIndex + HASHTABLE_CAPACITY;
// iterator for traversing values in table
typename list<DataType>::iterator it;
// if array location is not "occupied", copy into array
// else if keys match, replace the data
if (table[wrappedIndex].empty())
{
table[wrappedIndex].push_back(value);
count++;
return true;
}
else
{
it = find(table[wrappedIndex].begin(), table[wrappedIndex].end(), value);
if (it != table[wrappedIndex].end()) *it = value;
else {table[wrappedIndex].push_back(value); count++;}
}
return true;
}
// function for replacing values
template <class DataType>
bool HashTable<DataType>::replace(DataType &value)
{
// get wrapped index
int wrappedIndex = value.hashCode() % HASHTABLE_CAPACITY;
if (wrappedIndex < 0) wrappedIndex = wrappedIndex + HASHTABLE_CAPACITY;
if(table[wrappedIndex].empty()) return false;
// iterator for traversing the values in table
typename list<DataType>::const_iterator it;
it = find(table[wrappedIndex].begin(), table[wrappedIndex].end(), value);
if(it == table[wrappedIndex].end()) return false;
value = *it;
table[wrappedIndex].erase(it);
count--;
return true;
}
template <class DataType>
bool HashTable<DataType>::remove(DataType &value)
{
// get wrapped index
int wrappedIndex = value.hashCode() % HASHTABLE_CAPACITY;
if (wrappedIndex < 0) wrappedIndex = wrappedIndex + HASHTABLE_CAPACITY;
if(table[wrappedIndex].empty()) return false;
// iterator for traversing the values in table
typename list<DataType>::iterator it;
// if array location is not "occupied", copy into array
// else if keys match, remove the data
it = find(table[wrappedIndex].begin(), table[wrappedIndex].end(), value);
if(it == table[wrappedIndex].end()) return false;
value = *it;
table[wrappedIndex].erase(it);
count--;
return true;
}
// function for clearing the table of it's values
template <class DataType>
void HashTable<DataType>::clear()
{
count = 0;
currentIndex = -1;
for(int i = 0; i < HASHTABLE_CAPACITY; i++)
if( !table[i].empty()) table[i].clear();
}
template <class DataType>
int HashTable<DataType>::size() const
{
return count;
}
#endif
And this is the actual Game Of Life driver file:
// Lab 11b
#include <iostream>
using namespace std;
struct cell
{
int value; // equal to 1, so 0,0 is not a blank
int row; // any +/0/- value
int col; // any +/0/- value
bool operator==(const cell& c) const {return row == c.row && col == c.col;}
bool operator<(const cell& c) const {return (1000000 * row + col) < (1000000 * c.row + c.col);}
int hashCode() const {return 31 * row + col;}
};
#include "HashTable.h"
HashTable<cell> grid;
HashTable<cell> newGrid;
const int MINROW = -25;
const int MAXROW = 25;
const int MINCOL = -35;
const int MAXCOL = 35;
int neighborCount(int row, int col)
{
cell temp;
int count = 0;
for (temp.row = row - 1; temp.row <= row + 1; temp.row++)
for (temp.col = col - 1; temp.col <= col + 1; temp.col++)
if (temp.row != row || temp.col != col)
if (grid.retrieve(temp))
++count;
return count;
}
void initialize()
{
cout << "List the coordinates for living cells.\n";
cout << "Terminate the list with a special pair -1 -1\n";
cell temp;
while (true)
{
cin >> temp.row >> temp.col;
if (temp.row == -1 && temp.col == -1) break;
grid.insert(temp);
}
cin.ignore();
}
void print()
{
cell temp = {1};
cout << "\nThe current Life configuration is:\n";
for (temp.row = MINROW; temp.row <= MAXROW; temp.row++)
{
for (temp.col = MINCOL; temp.col <= MAXCOL; temp.col++)
if (grid.retrieve(temp))
cout << '*';
else
cout << ' ';
cout << endl;
}
cout << endl;
}
void update()
{
cell temp = {1};
newGrid.clear();
for (temp.row = MINROW; temp.row <= MAXROW; temp.row++)
for (temp.col = MINCOL; temp.col <= MAXCOL; temp.col++)
switch (neighborCount(temp.row, temp.col))
{
case 2:
if (grid.retrieve(temp)) newGrid.insert(temp);
break;
case 3:
newGrid.insert(temp);
break;
}
grid = newGrid;
};
int main()
{
cout << "Welcome to Conway's game of Life\n";
cout << "This game uses a grid in which\n";
cout << "each cell can either be occupied by an organism or not.\n";
cout << "The occupied cells change from generation to generation\n";
cout << "according to the number of neighboring cells which are alive.\n";
initialize();
print();
for (int i = 1; grid.size(); i++)
{
cout << "Generation " << i << ". Press ENTER to continue, X-ENTER to quit...\n";
if (cin.get() > 31) break;
update();
print();
}
return 0;
}
When I try to compile these files I get this error:
In file included from GameOfLife.cpp:16:
HashTable.h: In member function ‘bool HashTable<DataType>::retrieve(DataType&) [with DataType = cell]’:
GameOfLife.cpp:32: instantiated from here
HashTable.h:74: error: no matching function for call to ‘find(std::_List_iterator<cell>, std::_List_iterator<cell>, cell&)’
HashTable.h: In member function ‘bool HashTable<DataType>::insert(DataType&) [with DataType = cell]’:
GameOfLife.cpp:47: instantiated from here
HashTable.h:117: error: no matching function for call to ‘find(std::_List_iterator<cell>, std::_List_iterator<cell>, cell&)’
What could be the issue here?
You need to #include <algorithm> to get std::find. This is presumably what you want to use when you call find. You should avoid using namespace std, specially in headers.