In my project, I am using a header file for an arrayList. During the main method, I initialize an object of type arrayList where FriendToken is another class defined in my project. However, this gives me quite a few errors while compiling arrayList.h. Apparently, I cannot use the built-in copy method and the operator == is unrecognized for an object of type FriendToken. Should I overload the == operator for FriendToken and if so, how should I do that?
Both errors are marked in the body ArrayList.h.
ArrayList.h:
#ifndef arrayList_h
#define arrayList_h
#include "linearList.h"
#include <iostream>
#include <fstream>
#include <ostream>
using namespace std;
template<class T>
class arrayList : public linearList<T>
{
public:
// constructor, copy constructor and destructor
arrayList(int initialCapacity = 10);
arrayList(const arrayList<T>&);
~arrayList() {delete [] element;}
// ADT methods
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void output(ostream& out) const;
void changeLength1D(T*& a, int oldLength, int newLength);
// additional method
int capacity() const {return arrayLength;}
protected:
void checkIndex(int theIndex) const;
// throw illegalIndex if theIndex invalid
T* element; // 1D array to hold list elements
int arrayLength; // capacity of the 1D array
int listSize; // number of elements in list
};
template<class T>
arrayList<T>::arrayList(int initialCapacity)
{
// Constructor.
arrayLength = initialCapacity;
element = new T[arrayLength];
listSize = 0;
}
template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList)
{
// Copy constructor.
arrayLength = theList.arrayLength;
listSize = theList.listSize;
element = new T[arrayLength];
copy(theList.element, theList.element + listSize, element);
}
template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{
// Verify that theIndex is between 0 and
// listSize - 1.
if (theIndex < 0 || theIndex >= listSize)
{
cout << "index = " << theIndex << " size = "
<< listSize;
}
}
template<class T>
T& arrayList<T>::get(int theIndex) const
{
// Return element whose index is theIndex.
// Throw illegalIndex exception if no such
// element.
checkIndex(theIndex);
return element[theIndex];
}
template<class T>
int arrayList<T>::indexOf(const T& theElement)const
{
// Return index of first occurrence of theElement.
// search for theElement
int theIndex = (int) (find(element, element
+ listSize, theElement) - element);
// check if theElement was found
if (theIndex == listSize)
return -1; // not found
else return theIndex;
}
template<class T>
void arrayList<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.
checkIndex(theIndex);
// valid index, shift elements with higher index
//PROBLEM********************************************
copy(element + theIndex + 1, element + listSize,element + theIndex);
element[--listSize].~T(); // invoke destructor
}
template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement)
{
// Insert theElement.
if (theIndex < 0 || theIndex > listSize)
{// invalid index
// code to throw an exception comes here
}
// valid index, make sure we have space
if (listSize == arrayLength)
{
// no space, double capacity
changeLength1D(element, arrayLength,
2 * arrayLength);
arrayLength *= 2;
}
// shift elements right one position
//PROBLEM***************************************
copy_backward(element + theIndex, element + listSize, element + listSize + 1);
element[theIndex] = theElement;
listSize++;
}
template<class T>
void arrayList<T>::output(ostream& out) const
{
// Put the list into the stream out.
copy(element, element + listSize, ostream_iterator<T>(out, " "));
}
template <class T>
ostream& operator<<(ostream& out, const arrayList<T>& x)
{x.output(out); return out;}
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
if (newLength < 0)
throw illegalParameterValue();
T* temp = new T[newLength];
// new array
int number = min(oldLength, newLength);
// number to copy
copy(a, a + number, temp);
delete [] a;
// deallocate old memory
a = temp;
}
#endif
FriendToken.h
#ifndef FriendToken_h
#define FriendToken_h
#include <string>
using namespace std;
class FriendToken
{
private:
string birthDate, name, homeTown;
public:
FriendToken(string birthDate = "01/01", string name = "John, Smith", string homeTown = "New York");
string getBirthDate();
string getName();
string getHomeTown();
bool equals(FriendToken a);
};
#endif
FriendToken.cpp
#include "FriendToken.h"
#include <string>
using namespace std;
FriendToken::FriendToken(string birthDate, string name, string homeTown)
{
this->birthDate = birthDate;
this->name = name;
this->homeTown = homeTown;
}
string FriendToken::getBirthDate()
{
return birthDate;
}
string FriendToken:: getName()
{
return name;
}
string FriendToken::getHomeTown()
{
return homeTown;
}
bool FriendToken::equals(FriendToken a)
{
return (name == a.getName()) && (homeTown == a.getHomeTown()) && (birthDate == a.getBirthDate());
}
It's hard to tell without the compiler errors.
Either way, this is how you overload the operator.
template<typename T>
bool arrayList::operator== (const arrayList<T>& theList)
{
// Compare the values, and return a bool result.
}
Related
I am a beginner at c++ and I am coding a program that stores data into a BST template class the being another class called log_t that stores the variables, I am trying to use the inorder method from the BST class to reference a vector from main, to input the values into and be able to use it in the main class
my main class
int main(int argc, char* argv[])
{
BST<log_t> l;
string infilename = "";
string filePath = "data\\";
string files[1] = {
filePath + "MetData-31-3a.csv"
//filePath + "Jan20071toDec31abcdefghijklmnopq",
//filePath + "Jan20081toDec31abcdefghijklmnopq",
//filePath + "MetData_Jan01-2010-Jan01-2011-ALL"
};
/// checks if file can open
for (int i = 0; i < 1; i++) {
infilename = files[i];
ifstream infile(infilename);
if (!infile.is_open())
{
cout << "unable to read file" << files[i] << endl;
}
else
{
cout << "reading file" << files[i] << endl;
}
/* parse sensor data csv file */
string tmp;
getline(infile, tmp); // skip the first line
while (getline(infile, tmp))
{
// if successfully parsed then append into vector
log_t logline;
if (ParseLog(tmp, logline))
l.insert(logline);
}
}
cout << " end with reading file" << endl;
/* aggregate/filter logs */
Vector<log_t> vec;
l.inorder(vec);
/* prompt menu */
// this array stores all the menu option callback functions
void(*funs[])(const Vector<log_t> & vec) = { NULL, &option1, &option2, &option3, &option4, &option5,&option6 };
// keep printing menu in loop
while (true)
{
// prompt menu and ask user to select option
int choice = PromptMenu();
// check validity of choice
if (choice < 1 || choice > 6)
{
cout << "invalid choice" << endl;
}
else
{
cout << endl;
// call menu option handler
(funs[choice])(vec);
}
}
system("pause");
return -1;
}
my BST class
#include <string>
#include <iostream>
#include <stream>
#include <iomanip>
#include <stream>
#include "date.h"
#include "times.h"
#include "log_t.h"
#include "Vector.h"
using namespace std;
template <class T>
class BST {
private:
struct Node {
T num;
Node* left;
Node* right;
};
Node* root = NULL;
Node* insert(Node* node, T x);
Node* newnode(T num);
void removeprivate(T num, Node* parent);
T findsmallestprivate(Node* ptr);
void inorderprivate(Node* ptr, void (BST<T>::* FT)(T&), Vector<log_t>const& log);
void postorderprivate(Node* ptr, void (BST<T>::* FT)(T&));
void preorderprivate(Node* ptr, void (BST<T>::* FT)(T&));
//void inorderprivate(Node* ptr);
//void postorderprivate(Node* ptr);
//void preorderprivate(Node* ptr);
void removematch(Node* parent, Node* match, bool left);
public:
void insert(T num);
void remove(T num);
void removerootmatch();
T findsmallest();
void inorder(Vector<log_t>const& log);
void postorder();
void preorder();
void print(T& p) { cout << p << " "; };
};
template <class T>
void BST<T>::inorder(Vector<log_t>const& log) {
inorderprivate(root,print,log);
}
template <class T>
void BST<T>::inorderprivate(Node* ptr, void (BST<T>::* FT)(T&), Vector<log_t>const&
log) {
if (root != NULL)
{
if (ptr->left != NULL)
{
inorderprivate(ptr->left, FT);
}
(this->*FT)(log);
log.Append( ptr->num);
if (ptr->right != NULL)
{
inorderprivate(ptr->right, FT);
}
}
else
{
cout << "tree is empty";
}
}
my log_t class the T type
#pragma once
#ifndef LOG_T_H
#define LOG_T_H
#include <iostream>
#include <stream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <stream>
#include "date.h"
#include "times.h"
#include "BST.h"
class log_t
{
public:
log_t();
log_t(log_t& log);
float gettemp();
float getwind();
float getsolar();
void setwind(float wind);
void setsolar(float rad);
void settemp(float temp);
Date date;
Times time;
private:
float wind_speed;
float solar_radiation;
float air_temperature;
};
log_t::log_t()
{
wind_speed = 0;
solar_radiation = 0;
air_temperature = 0;
}
log_t::log_t(log_t& log) {
wind_speed = log.wind_speed;
solar_radiation = log.solar_radiation;
air_temperature = log.air_temperature;
date.SetDate(log.date.GetDay(), log.date.GetMonth(), log.date.GetYear());
time.SetHour(log.time.GetHour());
time.SetMinute(log.time.GetMinute());
}
float log_t:: gettemp()
{
return air_temperature;
}
float log_t::getwind() {
return wind_speed;
}
float log_t::getsolar() {
return solar_radiation;
}
void log_t::setwind(float wind)
{
wind_speed = wind;
}
void log_t::setsolar(float rad)
{
solar_radiation = rad;
}
void log_t::settemp(float temp)
{
air_temperature = temp;
}
#endif // LOG_T_H
my vector class
#pragma once
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <stream>
#include <string>
template <class T>
class Vector
{
public:
Vector();
Vector(int capacity);
Vector(const Vector& vec);
Vector& operator=(const Vector& vec);
~Vector();
int GetSize() const;
void Expand();
T& GetLast();
void Append(const T& val);
T& operator[](int idx);
const T& operator[](int idx) const;
private:
T* elems;
int capacity;/** < int capacity, stores the size of the array */
int count;
void CopyFrom(const Vector& vec);
};
template <class T>
inline Vector<T>::Vector() : elems(nullptr), capacity(0), count(0)
{
}
template <class T>
inline Vector<T>::Vector(int capacity)
: elems(new T[capacity]()), capacity(capacity), count(0)
{
}
template <class T>
inline Vector<T>::Vector(const Vector& vec)
{
CopyFrom(vec);
}
template <class T>
inline Vector<T>& Vector<T>::operator=(const Vector& vec)
{
if (elems)
delete[] elems;
CopyFrom(vec);
return *this;
}
template <class T>
inline Vector<T>::~Vector()
{
if (elems)
delete[] elems;
}
template <class T>
inline int Vector<T>::GetSize() const
{
return count;
}
template <class T>
inline void Vector<T>::Expand()
{
++count;
if (count > capacity)
if (capacity)
capacity *= 2;
else
capacity = 4;
T* tmp = new T[capacity]();
for (int i = 0; i < count - 1; ++i)
tmp[i] = elems[I];
if (elems)
delete[] elems;
elems = tmp;
}
template <class T>
inline T& Vector<T>::GetLast()
{
return elems[count - 1];
}
template <class T>
inline void Vector<T>::Append(const T& oval)
{
Expand();
GetLast() = val;
}
template <class T>
inline T& Vector<T>::operator[](int idx)
{
return elems[idx];
}
template <class T>
inline const T& Vector<T>::operator[](int idx) const
{
return elems[idx];
}
template <class T>
inline void Vector<T>::CopyFrom(const Vector& vec)
{
elems = new T[vec.capacity]();
capacity = vec.capacity;
count = vec.count;
for (int i = 0; i < count; ++i)
elems[i] = vec.elems[i];
}
#endif //VECTOR_H
the errors that keep showing up are
Severity Code Description Project File Line Suppression State
Error (active) E0147 declaration is incompatible with "void BST::inorder(const Vector<> &log)" (declared at line 241 of "C:\Users\Frances\Documents\A2\A2\BST.h") A2 C:\Users\Frances\Documents\A2\A2\BST.h 241
Severity Code Description Project File Line Suppression State
Error C2065 'log_t': undeclared identifier A2 C:\Users\Frances\Documents\A2\A2\BST.h 33
Severity Code Description Project File Line Suppression State
Error C2923 'Vector': 'log_t' is not a valid template type argument for parameter 'T' A2 C:\Users\Frances\Documents\A2\A2\BST.h 33
could someone help me figure out what it is that's causing this or what I am doing wrong, I have been trying to find an answer for hours and haven't been successful thank you
I have a assignment where I'm suppose to build template using these specifications.
ISet is a container that holds values of a certain where order doesn't matter and
which does not allow duplicates (or multiples).
A dynamically allocated array of type T should be used as an internal data structure for the Set.
The Set should inherit from the ISet interface below - this must not be modified:
template <typename T>
class ISet
{
public:
virtual bool insert (T element) = 0;
virtual bool remove (T element) = 0;
virtual int size () const = 0;
};
• insert (T element): adds elements to the set and returns true provided that
the element is not already present in the quantity (in which case the element is not added and false is returned).
• remove (T element): removes elements from the set and returns true.
If the element is missing in the quantity, false returns.
• size (): returns the number of elements in the set.
In addition to the member functions, you must implement constructor, destructor, copy constructor
and assignment operator.
And so far have I come up with this code:
#pragma once
#include <string>
#include <iostream>
using namespace std;
template <class T>
class ISet
{
public:
virtual bool insert(T element) = 0;
virtual bool remove(T element) = 0;
virtual int size() const = 0;
};
#pragma once
#include "ISet.h"
template <class T>
class Set : public ISet<T>
{
public:
Set(string name);
~Set();
Set(const Set &origin);
//Set& operator=(const Set &origin);
bool insert(T element);
bool remove(T element);
int size()const;
private:
string name;
T *arr;
int cap, nrOfElement;
};
template<class T>
Set<T>::Set(string name)
{
this->name = name;
this->cap = 10;
this->nrOfElement = 0;
this->arr = new T[this->cap];
}
template<class T>
Set<T>::~Set()
{
delete[] arr;
}
template<class T>
Set<T>::Set(const Set & origin)
{
this->nrOfElement = origin.nrOfElement;
this->cap = origin.cap;
arr = new T*[cap];
for (int i = 0; i < nrOfElement; i++)
{
arr[i] = origin.arr[i];
}
}
template<class T>
bool Set<T>::insert(T element)
{
bool found = false;
if (nrOfElement == 0)
{
this->arr[0] = element;
this->nrOfElement++;
}
else
{
for (int i = 0; i < this->nrOfElement; i++)
{
if (this->arr[i] == element)
{
i = this->nrOfElement;
found = true;
}
}
if (found == false)
{
this->arr[nrOfElement++] = element;
}
}
return found;
}
template<class T>
bool Set<T>::remove(T element)
{
bool removed = false;
for (int i = 0; i < this->nrOfElement; i++)
{
if (this->arr[i] == element)
{
this->arr[i] = this->arr[nrOfElement];
nrOfElement--;
removed = true;
}
}
return removed;
}
template<class T>
int Set<T>::size() const
{
return this->nrOfElement;
}
And my problems starts when I start to test this code by adding the different data-type we are suppose to test the template against.
#include "Set.h"
#include "ISet.h"
#include "Runner.h"
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
Set<string> test("test");
test.insert("lol");
cout << test.size();
test.remove("lol");
cout << test.size();
Set<Runner> test2("test");
getchar();
return 0;
}
Getting the error saying that "No operator found which takes a left-hand operand type of 'Runner'. So I have to create a operator== that handles this but don't know?
Runner class looks like this:
#pragma once
#include "Competitor.h"
#include <string>
using namespace std;
class Runner : public Competitor
{
public:
Runner();
Runner(string firstName, string lastName, int startNr);
~Runner();
void addResult(int resultTime);
int getResult() const;
string toString() const;
Runner *clone() const;
private:
int resultTime;
};
#include "Runner.h"
Runner::Runner()
{
this->resultTime = 0;
}
Runner::Runner(string firstName, string lastName, int startNr) : Competitor(firstName, lastName, startNr)
{
this->resultTime = 0;
}
Runner::~Runner()
{
}
void Runner::addResult(int resultTime)
{
this->resultTime = resultTime;
}
int Runner::getResult() const
{
return this->resultTime;
}
string Runner::toString() const
{
return (to_string(this->resultTime) + " sec");
}
Runner * Runner::clone() const
{
return new Runner(*this);
}
How do I build a operator== that will work for this?
You need to add operator== to the Runner class:
bool operator==(const Runner& other) const;
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm working on implementing a chain data structure, using a specific set of pre-made templates. Upon compilation, I'm receiving the error in the title.
arrayList.h:
#ifndef arrayList_h
#define arrayList_h
#include <iostream>
#include "linearList.h"
using namespace std;
template<class T>
class arrayList : public linearList<T>{
public:
//constructor, copy constructor, destructor
arrayList(int initialCapacity = 10);
arrayList(const arrayList<T>&);
~arrayList() {delete [] element;};
//ADT methods
bool empty() const {return listSize == 0;};
int size() const {return listSize;};
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void output(ostream& out) const;
//additional method
int capacity() const {return arrayLength;};
protected:
void checkIndex(int theIndex) const;
//throw illegalIndex if theIndex is invalid
T* element; //1D array to hold list elements
int arrayLength; //capacity of 1D array
int listSize; //number of elements in list
};
#endif
chain.h:
#ifndef chain_h
#define chain_h
#include <iostream>
#include "linearList.h"
#include "chainNode.h"
using namespace std;
template<class T>
class chain : public linearList<T>{
public:
// constructor and destructor
chain(int initialCapacity = 10);
//chain(const chain<T>&);
~chain();
// ADT methods
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void output(ostream& out) const;
protected:
void checkIndex(int theIndex) const;
chain<T>* firstNode;
int listSize;
};
#endif
chainNode.h:
#ifndef chainNode_h
#define chainNode_h
#include <iostream>
template <class T>
struct chainNode
{
// data members
T element;
chainNode<T> *next;
// methods
chainNode() {}
chainNode(const T& element)
{this->element = element;}
chainNode(const T& element, chainNode<T>* next)
{this->element = element;
this->next = next;}
};
#endif
chain.cpp:
#include "chain.h"
#include "person.h"
using namespace std;
template<class T>
chain<T>::chain(int initialCapacity){
// Constructor.
/*if (initialCapacity < 1){
ostringstream s;
s << "Initial capacity = "
<< initialCapacity << " Must be > 0";
throw illegalParameterValue(s.str());
}*/
firstNode = NULL;
listSize = 0;
}
template<class T>
chain<T>::~chain(){
// Chain destructor. Delete all nodes
// in chain.
while (firstNode != NULL){
// delete firstNode
chainNode<T>* nextNode = firstNode->next;
delete firstNode;
firstNode = nextNode;
}
}
template<class T>
T& chain<T>::get(int theIndex) const{
// Return element whose index is theIndex.
checkIndex(theIndex);
// move to desired node
chainNode<T>* currentNode = firstNode;
for (int i = 0; i < theIndex; i++)
currentNode = currentNode->next;
return currentNode->element;
}
template<class T>
int chain<T>::indexOf(const T& theElement) const{
// search the chain for theElement
chainNode<T>* currentNode = firstNode;
int index = 0; // index of currentNode
while (currentNode != NULL && currentNode->element != theElement){
// move to next node
currentNode = currentNode->next;
index++;
}
// make sure we found matching element
if (currentNode == NULL)
return -1;
else
return index;
}
template<class T>
void chain<T>::erase(int theIndex){
checkIndex(theIndex);
chainNode<T>* deleteNode;
if (theIndex == 0){
// remove first node from chain
deleteNode = firstNode;
firstNode = firstNode->next;
}
else{
// use p to get to beforeNode
chainNode<T>* p = firstNode;
for (int i = 0; i < theIndex - 1; i++)
p = p->next;
deleteNode = p->next;
p->next = p->next->next;
}
listSize--;
delete deleteNode;
}
template<class T>
void chain<T>::insert(int theIndex, const T& theElement){
if (theIndex < 0 || theIndex > listSize){
// THROW ILLEGAL EXCEPTION
}
if (theIndex == 0) // insert at front
firstNode = new chainNode<T>(theElement, firstNode);
else{
// find predecessor of new element
chainNode<T>* p = firstNode;
for (int i = 0; i < theIndex - 1; i++)
p = p->next;
// insert after p
p->next = new chainNode<T>(theElement, p->next);
}
listSize++;
}
Person.h:
#ifndef Person_h
#define Person_h
#include <string>
#include <sstream>
using namespace std;
class Person{
public:
//Variables
string birthdate;
string first_name;
string last_name;
string hometownID;
string hometownName;
string userID;
string name;
//Constructors
Person();
Person(string birthdate, string first_name, string last_name, string hometownID, string hometownName, string userID);
//Methods
string getBirthdate();
void setBirthdate(string birthdate);
string getFirst_name();
void setFirst_name(string first_name);
string getLast_name();
void setLast_name(string last_name);
string getName();
void setName(string name);
string getHometownID();
void setHometownID(string hometownID);
string getHometownName();
void setHometownName(string hometownName);
string getUserID();
void setUserID(string userID);
int compare(Person& p, int criteria);
//Comparisons
friend bool operator== (Person p1, Person p2);
friend bool operator!= (Person &p1, Person &p2);
friend bool operator> (Person &p1, Person &p2);
friend bool operator>= (Person &p1, Person &p2);
friend bool operator< (Person &p1, Person &p2);
friend bool operator<= (Person &p1, Person &p2);
friend ostream& operator<<(ostream& os, const Person& p);
};
#endif
Person.cpp: I've cut this down quite a bit. I currently don't have anything having to do with Node within this.
#include "Person.h"
#include <sstream>
#include <string>
using namespace std;
Person::Person(){
birthdate = "";
name = "";
hometownID = "";
hometownName = "";
userID = "";
}
Person::Person(string birthdate, string first_name, string last_name, string hometownID, string hometownName, string userID){
this->birthdate = birthdate;
this->first_name = first_name;
this->last_name = last_name;
this->hometownID = hometownID;
this->hometownName = hometownName;
this->userID = userID;
name = last_name+ ", " +first_name;
}
//mostly get/set methods after here, nothing having to do with node.
main.cpp:
#include "arrayList.cpp"
#include "block_allocator.h"
#include "chain.cpp"
#include "chainNode.h"
#include "json.h"
#include "linearList.h"
#include "Person.h"
#include <string>
#include <fstream>
#include <streambuf>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <time.h>
using namespace std;
//ArrayList helper methods
arrayList<Person> arrayListStructure(string fileName);
int arrayListSort(int criteria, arrayList<Person>* list);
void arrayListReverseSort(int criteria, arrayList<Person>* list);
int arrayListFlip(arrayList<Person>* list);
//Chain helper methods
chain<Person> chainStructure(string fileName);
//Hashtable helper methods
int main(int argc, const char * argv[]){
//get fileName
cout << "Please enter a filename:" << endl;
string fileName;
cin >> fileName;
//get data structure type
cout << "Please choose a data structure:" << endl;
cout << " 1. Arraylist" << endl;
cout << " 2. Chain" << endl;
cout << " 3. Hashtable" << endl;
int dataStructure;
cin >> dataStructure;
cout << "Please choose a criteria:" << endl;
cout << " 1. Name" << endl;
cout << " 2. Birthday" << endl;
cout << " 3. Location" << endl;
int criteria;
cin >> criteria;
arrayList<Person> friends;
chain<Person> friendChain;
//parse file into data structure
switch(dataStructure){
case 1: //Arraylist
//edited out, irrelevant
/*case 2:
//Chain
//code goes here
/*switch(criteria){
case 1: //Name
case 2: //Birthday
case 3: //Location
}
break;*/
/*case 3:
//Hashtable
//code goes here
break;
*/
}
}
//Helper methods for chain
chain<Person> chainStructure(string fileName){
//create initial (empty) chain
chain<Person> friends;
//open input file
ifstream fileInput(fileName);
//turn input stream into string
string inputStr((istreambuf_iterator<char>(fileInput)), istreambuf_iterator<char>());
//parse file content into json object
char *errorPos = 0;
char *errorDesc = 0;
int errorLine = 0;
block_allocator allocator(1 << 10);
json_value *root = json_parse(const_cast<char*>(inputStr.c_str()), &errorPos, &errorDesc, &errorLine, &allocator);
//Take value of first element
json_value *list = root->first_child;
//Outer loop addresses each friend's JSON object
for(json_value *it = list->first_child; it; it = it->next_sibling){
string first_name, last_name, birthdate, hometownID, hometownName, userID;
//Inner loop looks at each key/value pair within each friend object
for(json_value *friendKeys = it->first_child; friendKeys; friendKeys = friendKeys->next_sibling){
//grab first name
if(!string(friendKeys->name).compare("first_name")){
first_name = friendKeys->string_value;
}
//grab last name
else if(!string(friendKeys->name).compare("last_name")){
last_name = friendKeys->string_value;
}
//grab birthday and trim to 5 characters
else if(!string(friendKeys->name).compare("birthday")){
birthdate = friendKeys->string_value;
birthdate = birthdate.substr(0, 5);
}
//grab hometown info
else if(!string(friendKeys->name).compare("hometown")){
for(json_value *hometownKeys = friendKeys->first_child; hometownKeys; hometownKeys = hometownKeys->next_sibling){
if(!string(hometownKeys->name).compare("id")){
hometownID = hometownKeys->string_value;
}
if(!string(hometownKeys->name).compare("name")){
hometownName = hometownKeys->string_value;
}
}
}
//grab userID
else if(!string(friendKeys->name).compare("id")){
userID = friendKeys->string_value;
}
}
if(birthdate != "" && first_name != "" && last_name != "" && hometownID != "" && hometownName != "" && userID != ""){
//Create new Person in chain
Person person(birthdate, first_name, last_name, hometownID, hometownName, userID);
friends.insert(friends.size(), person);
}
}
//return friends;
return friends;
}
//Helper methods for hashtable
So I know this is a huge wall of text, but I'm really not sure where this disconnect is, and I didn't want to provide too little information. Any help or advice would be greatly appreciated, as I'm very new to C++, and even more inexperienced with using the template system.
EDIT: linearList.h:
#ifndef linearList_h
#define linearList_h
#include <iostream>
using namespace std;
template<class T>
class linearList
{
public:
virtual ~linearList() {};
virtual bool empty() const = 0;
// return true iff list is empty
virtual int size() const = 0;
// return number of elements in list
virtual T& get(int theIndex) const = 0;
// return element whose index is theIndex
virtual int indexOf(const T& theElement) const = 0;
// return index of first occurence of theElement
virtual void erase(int theIndex) = 0;
// remove the element whose index is theIndex
virtual void insert(int theIndex, const T& theElement) = 0;
// insert theElement so that its index is theIndex
virtual void output(ostream& out) const = 0;
// insert list into stream out
};
#endif
In chain.h, the chain<T> template has this for a member:
chain<T>* firstNode;
I'm pretty sure that should be:
chainNode<T>* firstNode;
There may be other errors (or maybe not), but that appears the likely one causing your current issue that is the subject of this question.
Side Bar: This thing needs a serious refactor to use the containers and algorithms from the standard library (std::vector<T>, std::list<T>, etc...) Just consider it.
I currently have a Person class, and have created a PersonList class that extends List, specifically for objects of type Person. When I instantiate a new PersonList I get one error that stops the entire build from happening successfully:
error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Person' (or there is no acceptable conversion) c:\program files\microsoft visual studio 11.0\vc\include\xutility 3186 1 ConsoleApplication3
Here is the PersonList class:
#pragma once
#include<iostream>
#include<sstream>
#include<string>
#include<algorithm>
#include "linearList.h"
#include "myExceptions.h"
#include "changeLength1D.h"
#include <Person.h>
using namespace std;
template<class Person>
class PersonList: public linearList<Person>
{
public:
PersonList(int initialCapacity = 10);
PersonList(const PersonList<Person>&);
~PersonList() {delete [] element;}
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
Person& get(int theIndex) const;
int indexOf(const Person& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const Person& theElement);
void output(ostream& out) const;
// additional method
int capacity() const {return arrayLength;}
protected:
void checkIndex(int theIndex) const;
// throw illegalIndex if theIndex invalid
Person* element; // 1D array to hold list elements
int arrayLength; // capacity of the 1D array
int listSize; // number of elements in list
};
template<class Person>
PersonList<Person>::PersonList(int initialCapacity)
{// Constructor.
if (initialCapacity < 1)
{ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
throw illegalParameterValue(s.str());
}
arrayLength = initialCapacity;
element = new Person[arrayLength];
listSize = 0;
}
template<class Person>
PersonList<Person>::PersonList(const PersonList<Person>& theList)
{// Copy constructor.
arrayLength = theList.arrayLength;
listSize = theList.listSize;
element = new Person[arrayLength];
copy(theList.element, theList.element + listSize, element);
}
template<class Person>
void PersonList<Person>::checkIndex(int theIndex) const
{// Verify that theIndex is between 0 and listSize - 1.
if (theIndex < 0 || theIndex >= listSize)
{ostringstream s;
s << "index = " << theIndex << " size = " << listSize;
throw illegalIndex(s.str());
}
}
template<class Person>
Person& PersonList<Person>::get(int theIndex) const
{// Return element whose index is theIndex.
// Throw illegalIndex exception if no such element.
checkIndex(theIndex);
return element[theIndex];
}
template<class Person>
int PersonList<Person>::indexOf(const Person& theElement) const
{// Return index of first occurrence of theElement.
// Return -1 if theElement not in list.
// search for theElement
int theIndex = (int) (find(element, element + listSize, theElement)
- element);
// check if theElement was found
if (theIndex == listSize)
// not found
return -1;
else return theIndex;
}
template<class Person>
void PersonList<Person>::erase(int theIndex)
{// Delete the element whose index is theIndex.
// Throw illegalIndex exception if no such element.
checkIndex(theIndex);
// valid index, shift elements with higher index
copy(element + theIndex + 1, element + listSize,
element + theIndex);
element[--listSize].~Person(); // invoke destructor
}
template<class Person>
void PersonList<Person>::insert(int theIndex, const Person& theElement)
{// Insert theElement so that its index is theIndex.
if (theIndex < 0 || theIndex > listSize)
{// invalid index
ostringstream s;
s << "index = " << theIndex << " size = " << listSize;
throw illegalIndex(s.str());
}
// valid index, make sure we have space
if (listSize == arrayLength)
{// no space, double capacity
changeLength1D(element, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
// shift elements right one position
copy_backward(element + theIndex, element + listSize,
element + listSize + 1);
element[theIndex] = theElement;
listSize++;
}
template<class Person>
void PersonList<Person>::output(ostream& out) const
{// Put the list into the stream out.
copy(element, element + listSize, ostream_iterator<Person>(cout, " "));
}
// overload <<
template <class Person>
ostream& operator<<(ostream& out, const PersonList<Person>& x)
{x.output(out); return out;}
The Person Class:
#pragma once
#include <string>
using namespace std;
class Person
{
public:
Person(string firstName, string lastName, string birthday, string hometown);
Person(void);
~Person(void);
string name;
string birthday;
string hometown;
};
The same thing happens in an arrayList class I tried using earlier. Is there a way to get it so I can simply store person objects in an ArrayList type structure?
Your function indexOf() contains a call to STL's std::find() algorithm, which internally performs comparisons between pairs of values to determine if the element passed as a third argument is contained in the range defined by the first two arguments.
To perform this comparison, std::find() uses the == operator. However, no operator == has been defined for objects of type Person.
In order to solve the problem, you must overload the comparison operator == for instances of Person. You can do it, for instance, this way:
class Person
{
...
public:
friend bool operator == (Person const& p1, Person const& p2)
{
// Perform the comparison and return "true" if the objects are equal
return (p1.name == p2.name) && ...
}
};
###MyClass.h###
#ifndef _MyClass
#define _MyClass
#include <string>
using namespace std;
class MyClass
{
public:
MyClass(const string name, const string text);
void display(ostream & out) const;
MyClass & operator = (const MyClass & m);
int compare(const MyClass & right) const;
private:
string _name;
string _text;
};
bool operator < (const MyClass & left, const MyClass & right);
ostream & operator << (ostream & out, const MyClass & mc);
#endif
###Node.h###
#include <string>
#include "MyClass.h"
using namespace std;
typedef MyClass * DataType;
class Node
{
private:
DataType item; // data
Node * lchild; // left child pointer
Node * rchild; // right child pointer
public:
Node(DataType Item);
DataType getItem() const;
void setItem(const DataType & data);
Node* getLChild() const;
void setLChild(Node * p);
Node* getRChild() const;
void setRChild(Node * p);
virtual ~Node();
};
###BST.h###
#include "Node.h"
using namespace std;
class BST
{
private:
Node * root;
bool Search(const DataType item, Node * r) const;
void Insert (DataType item, Node * ptr);
void Destructor(const Node * r);
public:
BST();
bool IsEmpty() const;
void Insert(const DataType item);
bool Search(const DataType item) const;
virtual ~BST();
};
###MyClass.cpp###
#include <iostream>
#include "MyClass.h"
using namespace std;
MyClass::MyClass(const string name, const string text)
{
_name = name;
_text = text;
}
void MyClass::display(ostream & out) const
{
out << "Name: " << _name << endl;
out << "Text: " << _text << endl;
}
MyClass & MyClass::operator = (const MyClass & m)
{
if (this == & m)
return *this;
_name = m._name;
_text = m._text;
return *this;
}
int MyClass::compare(const MyClass & right) const
{
return _name.compare(right._name);
}
bool operator < (const MyClass & left, const MyClass & right)
{
return left.compare(right) > 0;
}
ostream & operator << (ostream & out, const MyClass & mc)
{
mc.display(out);
return out;
}
###Node.cpp###
#include "Node.h"
Node::Node(DataType Item):item(Item)
{
lchild = 0;
rchild = 0;
}
DataType Node::getItem() const
{
DataType anItem = item;
return anItem;
}
void Node::setItem( const DataType & data)
{
item = data;
}
Node* Node::getLChild() const
{
Node * p = lchild;
return p;
}
void Node::setLChild(Node * p)
{
lchild = p;
}
Node* Node::getRChild() const
{
Node * p = rchild;
return p;
}
void Node::setRChild(Node * p)
{
rchild = p;
}
Node::~Node()
{
}
###BST.cpp###
#include <iostream>
#include "BST.h"
using namespace std;
bool BST::Search(const DataType item) const
{
return Search(item, root);
}
bool BST::Search(const DataType item, Node * r) const
{
if(r != 0)
{
if (item == r->getItem())
return true;
else
{
if (item < r->getItem())
return Search(item, r->getLChild());
else
return Search(item, r->getRChild());
}
}
else
return false;
}
BST::BST()
{
root = 0;
}
bool BST::IsEmpty() const
{
return (root == 0);
}
void BST::Insert(const DataType item)
{
if(root == 0)
root = new Node(item);
else
Insert(item, root);
}
void BST::Insert(DataType item, Node * ptr)
{
if (item < ptr->getItem())
{
if (ptr->getLChild() == 0)
ptr->setLChild(new Node(item));
else
Insert(item, ptr->getLChild());
}
else
{
if (ptr->getRChild() == 0)
ptr->setRChild(new Node(item));
else
Insert(item, ptr->getRChild());
}
}
void BST::Destructor(const Node * r)
{
if(r!=0)
{
Destructor( r->getLChild());
Destructor( r->getRChild());
delete r;
}
}
BST::~BST()
{
Destructor(root);
}
###main.cpp###
#include <iostream>
#include "MyClass.h"
#include "BST.h"
using namespace std;
void main()
{
MyClass * mc1 = new MyClass("Tree","This is a tree");
MyClass * mc2 = new MyClass("Book","This is a book");
MyClass * mc3 = new MyClass("Zoo","This is a zoo");
BST * tree = new BST();
tree->Insert(mc1);
tree->Insert(mc2);
tree->Insert(mc3);
cout << boolalpha << ("Book" < "Tree") << endl;
cout << (mc2 < mc1) << endl;
cout << (tree->Search(new MyClass("Book",""))) << endl;
}
Result is true false false
I don't know what's wrong with my operator overloading? (mc2 should
less than mc1)
I'm not sure if this is correct for searching a "MyClass" node in a BST?
and the result is "not found"....I traced it into "BST.cpp",
and found that the problem also occurs at " if (item < r->getItem()) "
Can anyone help me or give me a hint....thank you so much!
Here you are just comparing pointers, i.e memory addresses:
cout << (mc2 < mc1) << endl;
To compare the objects, you need to dereference the pointers:
cout << ((*mc2) < (*mc1)) << endl;
In your code snippet, there is no reason for mc1, mc2, etc. to be pointers, so you could avoid the problem by creating objects on the stack directly:
MyClass mc1("Tree","This is a tree");
and so on. I would even go further and say that you should only dynamically allocate objects with new if you really are sure you need to and have good reasons not to allocate automatically on the stack. And if you really must use dynamically allocated pointers, have a look at C++ smart pointers.