Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm totally at wit's end: I can't figure out how my dependency issues. I've read countless posts and blogs and reworked my code so many times that I can't even remember what almost worked and what didnt. I continually get not only redefinition errors, but class not defined errors. I rework the header guards and remove some errors simply to find others. I somehow got everything down to one error but then even that got broke while trying to fix it.
Would you please help me figure out the problem?
card.cpp
#include <iostream>
#include <cctype>
#include "card.h"
using namespace std;
// ====DECL======
Card::Card()
{
abilities = 0;
flavorText = 0;
keywords = 0;
artifact = 0;
classType = new char[strlen("Card") + 1];
classType = "Card";
}
Card::~Card (){
delete name;
delete abilities;
delete flavorText;
artifact = NULL;
}
// ------------
Card::Card(const Card & to_copy)
{
name = new char[strlen(to_copy.name) +1]; // creating dynamic array
strcpy(to_copy.name, name);
type = to_copy.type;
color = to_copy.color;
manaCost = to_copy.manaCost;
abilities = new char[strlen(to_copy.abilities) +1];
strcpy(abilities, to_copy.abilities);
flavorText = new char[strlen(to_copy.flavorText) +1];
strcpy(flavorText, to_copy.flavorText);
keywords = new char[strlen(to_copy.keywords) +1];
strcpy(keywords, to_copy.keywords);
inPlay = to_copy.inPlay;
tapped = to_copy.tapped;
enchanted = to_copy.enchanted;
cursed = to_copy.cursed;
if (to_copy.type != ARTIFACT)
artifact = to_copy.artifact;
}
// ====DECL=====
int Card::equipArtifact(Artifact* to_equip){
artifact = to_equip;
}
Artifact * Card::unequipArtifact(Card * unequip_from){
Artifact * to_remove = artifact;
artifact = NULL;
return to_remove;
// put card in hand or in graveyard
}
int Card::enchant( Card * to_enchant){
to_enchant->enchanted = true;
cout << "enchanted" << endl;
}
int Card::disenchant( Card * to_disenchant){
to_disenchant->enchanted = false;
cout << "Enchantment Removed" << endl;
}
// ========DECL=====
Spell::Spell()
{
currPower = basePower;
currToughness = baseToughness;
classType = new char[strlen("Spell") + 1];
classType = "Spell";
}
Spell::~Spell(){}
// ---------------
Spell::Spell(const Spell & to_copy){
currPower = to_copy.currPower;
basePower = to_copy.basePower;
currToughness = to_copy.currToughness;
baseToughness = to_copy.baseToughness;
}
// =========
int Spell::attack( Spell *& blocker ){
blocker->currToughness -= currPower;
currToughness -= blocker->currToughness;
}
//==========
int Spell::counter (Spell *& to_counter){
cout << to_counter->name << " was countered by " << name << endl;
}
// ============
int Spell::heal (Spell *& to_heal, int amountOfHealth){
to_heal->currToughness += amountOfHealth;
}
// -------
Creature::Creature(){
summoningSick = true;
}
// =====DECL======
Land::Land(){
color = NON;
classType = new char[strlen("Land") + 1];
classType = "Land";
}
// ------
int Land::generateMana(int mana){
// ... //
}
card.h
#ifndef CARD_H
#define CARD_H
#include <cctype>
#include <iostream>
#include "conception.h"
class Artifact;
class Spell;
class Card : public Conception
{
public:
Card();
Card(const Card &);
~Card();
protected:
char* name;
enum CardType { INSTANT, CREATURE, LAND, ENCHANTMENT, ARTIFACT, PLANESWALKER};
enum CardColor { WHITE, BLUE, BLACK, RED, GREEN, NON };
CardType type;
CardColor color;
int manaCost;
char* abilities;
char* flavorText;
char* keywords;
bool inPlay;
bool tapped;
bool cursed;
bool enchanted;
Artifact* artifact;
virtual int enchant( Card * );
virtual int disenchant (Card * );
virtual int equipArtifact( Artifact* );
virtual Artifact* unequipArtifact(Card * );
};
// ------------
class Spell: public Card
{
public:
Spell();
~Spell();
Spell(const Spell &);
protected:
virtual int heal( Spell *&, int );
virtual int attack( Spell *& );
virtual int counter( Spell*& );
int currToughness;
int baseToughness;
int currPower;
int basePower;
};
class Land: public Card
{
public:
Land();
~Land();
protected:
virtual int generateMana(int);
};
class Forest: public Land
{
public:
Forest();
~Forest();
protected:
int generateMana();
};
class Creature: public Spell
{
public:
Creature();
~Creature();
protected:
bool summoningSick;
};
class Sorcery: public Spell
{
public:
Sorcery();
~Sorcery();
protected:
};
#endif
conception.h -- this is an "uber class" from which everything derives
class Conception{
public:
Conception();
~Conception();
protected:
char* classType;
};
conception.cpp
Conception::Conception{
Conception(){
classType = new char[11];
char = "Conception";
}
game.cpp -- this is an incomplete class as of this code
#include <iostream>
#include <cctype>
#include "game.h"
#include "player.h"
Battlefield::Battlefield(){
card = 0;
}
Battlefield::~Battlefield(){
delete card;
}
Battlefield::Battlefield(const Battlefield & to_copy){
}
// ===========
/*
class Game(){
public:
Game();
~Game();
protected:
Player** player; // for multiple players
Battlefield* root; // for battlefield
getPlayerMove(); // ask player what to do
addToBattlefield();
removeFromBattlefield();
sendAttack();
}
*/
#endif
game.h
#ifndef GAME_H
#define GAME_H
#include "list.h"
class CardList();
class Battlefield : CardList{
public:
Battlefield();
~Battlefield();
protected:
Card* card; // make an array
};
class Game : Conception{
public:
Game();
~Game();
protected:
Player** player; // for multiple players
Battlefield* root; // for battlefield
getPlayerMove(); // ask player what to do
addToBattlefield();
removeFromBattlefield();
sendAttack();
Battlefield* field;
};
list.cpp
#include <iostream>
#include <cctype>
#include "list.h"
// ==========
LinkedList::LinkedList(){
root = new Node;
classType = new char[strlen("LinkedList") + 1];
classType = "LinkedList";
};
LinkedList::~LinkedList(){
delete root;
}
LinkedList::LinkedList(const LinkedList & obj)
{
// code to copy
}
// ---------
// =========
int LinkedList::delete_all(Node* root){
if (root = 0)
return 0;
delete_all(root->next);
root = 0;
}
int LinkedList::add( Conception*& is){
if (root == 0){
root = new Node;
root->next = 0;
}
else
{
Node * curr = root;
root = new Node;
root->next=curr;
root->it = is;
}
}
int LinkedList::remove(Node * root, Node * prev, Conception* is){
if (root = 0)
return -1;
if (root->it == is){
root->next = root->next;
return 0;
}
remove(root->next, root, is);
return 0;
}
Conception* LinkedList::find(Node*& root, const Conception* is, Conception* holder = NULL)
{
if (root==0)
return NULL;
if (root->it == is){
return root-> it;
}
holder = find(root->next, is);
return holder;
}
Node* LinkedList::goForward(Node * root){
if (root==0)
return root;
if (root->next == 0)
return root;
else
return root->next;
}
// ============
Node* LinkedList::goBackward(Node * root){
root = root->prev;
}
list.h
#ifndef LIST_H
#define LIST_H
#include <iostream>
#include "conception.h"
class Node : public Conception {
public:
Node() : next(0), prev(0), it(0)
{ it = 0;
classType = new char[strlen("Node") + 1];
classType = "Node";
};
~Node(){
delete it;
delete next;
delete prev;
}
Node* next;
Node* prev;
Conception* it; // generic object
};
// ----------------------
class LinkedList : public Conception {
public:
LinkedList();
~LinkedList();
LinkedList(const LinkedList&);
friend bool operator== (Conception& thing_1, Conception& thing_2 );
protected:
virtual int delete_all(Node*);
virtual int add( Conception*& ); //
virtual Conception* find(Node *&, const Conception*, Conception* ); //
virtual int remove( Node *, Node *, Conception* ); // removes question with keyword int display_all(node*& );
virtual Node* goForward(Node *);
virtual Node* goBackward(Node *);
Node* root;
// write copy constrcutor
};
// =============
class CircularLinkedList : public LinkedList {
public:
// CircularLinkedList();
// ~CircularLinkedList();
// CircularLinkedList(const CircularLinkedList &);
};
class DoubleLinkedList : public LinkedList {
public:
// DoubleLinkedList();
// ~DoubleLinkedList();
// DoubleLinkedList(const DoubleLinkedList &);
protected:
};
// END OF LIST Hierarchy
#endif
player.cpp
#include <iostream>
#include "player.h"
#include "list.h"
using namespace std;
Library::Library(){
root = 0;
}
Library::~Library(){
delete card;
}
// ====DECL=========
Player::~Player(){
delete fname;
delete lname;
delete deck;
}
Wizard::~Wizard(){
delete mana;
delete rootL;
delete rootH;
}
// =====Player======
void Player::changeName(const char[] first, const char[] last){
char* backup1 = new char[strlen(fname) + 1];
strcpy(backup1, fname);
char* backup2 = new char[strlen(lname) + 1];
strcpy(backup1, lname);
if (first != NULL){
fname = new char[strlen(first) +1];
strcpy(fname, first);
}
if (last != NULL){
lname = new char[strlen(last) +1];
strcpy(lname, last);
}
return 0;
}
// ==========
void Player::seeStats(Stats*& to_put){
to_put->wins = stats->wins;
to_put->losses = stats->losses;
to_put->winRatio = stats->winRatio;
}
// ----------
void Player::displayDeck(const LinkedList* deck){
}
// ================
void CardList::findCard(Node* root, int id, NodeCard*& is){
if (root == NULL)
return;
if (root->it.id == id){
copyCard(root->it, is);
return;
}
else
findCard(root->next, id, is);
}
// --------
void CardList::deleteAll(Node* root){
if (root == NULL)
return;
deleteAll(root->next);
root->next = NULL;
}
// ---------
void CardList::removeCard(Node* root, int id){
if (root == NULL)
return;
if (root->id = id){
root->prev->next = root->next; // the prev link of root, looks back to next of prev node, and sets to where root next is pointing
}
return;
}
// ---------
void CardList::addCard(Card* to_add){
if (!root){
root = new Node;
root->next = NULL;
root->prev = NULL;
root->it = &to_add;
return;
}
else
{
Node* original = root;
root = new Node;
root->next = original;
root->prev = NULL;
original->prev = root;
}
}
// -----------
void CardList::displayAll(Node*& root){
if (root == NULL)
return;
cout << "Card Name: " << root->it.cardName;
cout << " || Type: " << root->it.type << endl;
cout << " --------------- " << endl;
if (root->classType == "Spell"){
cout << "Base Power: " << root->it.basePower;
cout << " || Current Power: " << root->it.currPower << endl;
cout << "Base Toughness: " << root->it.baseToughness;
cout << " || Current Toughness: " << root->it.currToughness << endl;
}
cout << "Card Type: " << root->it.currPower;
cout << " || Card Color: " << root->it.color << endl;
cout << "Mana Cost" << root->it.manaCost << endl;
cout << "Keywords: " << root->it.keywords << endl;
cout << "Flavor Text: " << root->it.flavorText << endl;
cout << " ----- Class Type: " << root->it.classType << " || ID: " << root->it.id << " ----- " << endl;
cout << " ******************************************" << endl;
cout << endl;
// -------
void CardList::copyCard(const Card& to_get, Card& put_to){
put_to.type = to_get.type;
put_to.color = to_get.color;
put_to.manaCost = to_get.manaCost;
put_to.inPlay = to_get.inPlay;
put_to.tapped = to_get.tapped;
put_to.class = to_get.class;
put_to.id = to_get.id;
put_to.enchanted = to_get.enchanted;
put_to.artifact = to_get.artifact;
put_to.class = to_get.class;
put.to.abilities = new char[strlen(to_get.abilities) +1];
strcpy(put_to.abilities, to_get.abilities);
put.to.keywords = new char[strlen(to_get.keywords) +1];
strcpy(put_to.keywords, to_get.keywords);
put.to.flavorText = new char[strlen(to_get.flavorText) +1];
strcpy(put_to.flavorText, to_get.flavorText);
if (to_get.class = "Spell"){
put_to.baseToughness = to_get.baseToughness;
put_to.basePower = to_get.basePower;
put_to.currToughness = to_get.currToughness;
put_to.currPower = to_get.currPower;
}
}
// ----------
player.h
#ifndef player.h
#define player.h
#include "list.h"
// ============
class CardList() : public LinkedList(){
public:
CardList();
~CardList();
protected:
virtual void findCard(Card&);
virtual void addCard(Card* );
virtual void removeCard(Node* root, int id);
virtual void deleteAll();
virtual void displayAll();
virtual void copyCard(const Conception*, Node*&);
Node* root;
}
// ---------
class Library() : public CardList(){
public:
Library();
~Library();
protected:
Card* card;
int numCards;
findCard(Card&); // get Card and fill empty template
}
// -----------
class Deck() : public CardList(){
public:
Deck();
~Deck();
protected:
enum deckColor { WHITE, BLUE, BLACK, RED, GREEN, MIXED };
char* deckName;
}
// ===============
class Mana(int amount) : public Conception {
public:
Mana() : displayTotal(0), classType(0)
{ displayTotal = 0;
classType = new char[strlen("Mana") + 1];
classType = "Mana";
};
protected:
int accrued;
void add();
void remove();
int displayTotal();
}
inline Mana::add(){ accrued += 1; }
inline Mana::remove(){ accrued -= 1; }
inline Mana::displayTotal(){ return accrued; }
// ================
class Stats() : public Conception {
public:
friend class Player;
friend class Game;
Stats() : wins(0), losses(0), winRatio(0) {
wins = 0; losses = 0;
if ( (wins + losses != 0)
winRatio = wins / (wins + losses);
else
winRatio = 0;
classType = new char[strlen("Stats") + 1];
classType = "Stats";
}
protected:
int wins;
int losses;
float winRatio;
void int getStats(Stats*& );
}
// ==================
class Player() : public Conception{
public:
Player() : wins(0), losses(0), winRatio(0) {
fname = NULL;
lname = NULL;
stats = NULL;
CardList = NULL;
classType = new char[strlen("Player") + 1];
classType = "Player";
};
~Player();
Player(const Player & obj);
protected:
// member variables
char* fname;
char* lname;
Stats stats; // holds previous game statistics
CardList* deck[]; // hold multiple decks that player might use - put ll in this
private:
// member functions
void changeName(const char[], const char[]);
void shuffleDeck(int);
void seeStats(Stats*& );
void displayDeck(int);
chooseDeck();
}
// --------------------
class Wizard(Card) : public Player(){
public:
Wizard() : { mana = NULL; rootL = NULL; rootH = NULL};
~Wizard();
protected:
playCard(const Card &);
removeCard(Card &);
attackWithCard(Card &);
enchantWithCard(Card &);
disenchantWithCard(Card &);
healWithCard(Card &);
equipWithCard(Card &);
Mana* mana[];
Library* rootL; // Library
Library* rootH; // Hand
}
#endif
At least one of your problems is that in "player.h" you have
#ifndef player.h
#define player.h
"player.h" is not a legal pre-processor symbol. Did you mean
#ifndef player_h
#define player_h
?
Secondly, conception.cpp doesn't #include anything.
Third, your class definitions are largely invalid.
class Foo()
is not legal, nor is
class Foo() : public class Bar()
What does '()' have to do with a class name? Are you thinking of the constructor?
Then there is this
char = "Conception";
You can't assign a value to a type.
----- Feedback to help you clean up the code -----
. Choose a style
Or - if you are working with someone else's code, take theirs.
But stick with it.
A huge percentage of software defects that make it past initial development are there because they were hard to spot - missing semi-colons, missing {s around compound statements, etc. C.f. "CARD_H" vs "player.h".
. Inconsistency is the mother of most bugs
classType = new char[11];
char = "Conception";
You probably mean
classType = new char[11];
classType = "Conception";
but this is a memory leak and a bug waiting to happen. In Card:: you do it more correctly
name = new char[strlen(to_copy.name) +1]; // creating dynamic array
strcpy(to_copy.name, name);
The version you use elsewhere
classType = new ...
classType = "String";
allocates some memory, stores the address in classType. Then it looks up the variable of the compiled char* array "String\0" and stores it's address in classType instead.
When the class goes away, it will try to delete the static string and crash.
If this is a learning exercise and you're trying to learn about memory management, this general approach may be fair enough. But placing ownership of pointers in your classes like this is a sure-fire way to wind up with memory leaks and undefined behavior bugs.
It's best to encapsulate pointers in an RAII-style class (a class which owns the pointer and does the delete when it goes out of scope). Take a look into "std::unique_ptr", "std::shared_ptr" and "std::weak_ptr". For your purposes, "std::string" may help you reduce the number of defects by eliminating a lot of the managerial overhead.
. Try to avoid mixing initializer lists with assignment lists.
It's generally better to use one or the other. You can probably get away with using initializer lists when all of your members can be initialized that way, but if they can't, it may be better to use assignment.
Foo() : m_a(), m_b(), m_c() { m_b = 1; m_c = 2; } // is m_a not having a value a bug or intentional?
. Distinguish member variables from ordinary variables.
You're going to run into bugs where values dissapear on you as a result of shadowing: Shadowing variables
#include <iostream>
int i = 0;
int main() {
int i = 1;
for (int i = 0; i < 10; ++i) {
int i = 2 * i;
std::cout << i << std::endl;
}
return 0;
}
when you don't distinguish your member variables (a lot of people use an "m_" prefix, others use a "_" suffix) this is GOING to happen to you frequently.
. Don't assign numeric values to pointers.
name = 0;
while this compiles, you're setting yourself up for less obvious cases appearing to be numbers and Bad Things Ensuing.
abilities = 0;
No, I'm superman, I have ALL the abilities.
abilities = 42;
Two more correct ways to do this would be
name = NULL; // Traditional C++
or
name = nullptr; // C++11
You've done this in someplaces, again consistency is failing you.
. (minor but it'll bite you in the ass in a few weeks) "it" is generally used to reference an "iterator", you might want to use "data" or "value" or "element".
. avoid making members of classes/objects public.
Your "Node" class looks incredibly buggy (the destructor deletes both prev and next???) and you can't tell, from looking at the class, how the "it" pointer gets set, presumably because that happens elsewhere. Where else do you tamper with the "it", prev and next pointers? Encapsulate.
. 'const' can be your friend (by being a pain in your ass)
if (to_get.class = "Spell"){
This will assign "Spell" to to_get.class, causing a memory leak and other issues, and then succeed -- "Spell" evaluates to a fixed const char* address, which is non-zero, which is therefore true.
(It also doesn't compile because 'class' is a keyword and the actual variable is 'className').
You can prevent this by protecting your actual members and only exposing them thru carefully chosen accessors.
const char* Class() const { return m_className; }
Let me break this one down:
const char* :- you cannot modify the contents,
Class() :- instead of to_get.class you'll use to_get.Class()
const :- this function does not have side-effects on the object
The last part means that it can be used on a const object.
class Beer {
bool m_isFull;
public:
Beer() : m_isFull(true) {}
// non-const function, has side-effects (changes isFull);
void drink() { m_isFull = false; }
// const function, returns a copy of "m_isFull". you can
// change the value that's returned, but it doesn't affect us.
void isFull() const { return m_isFull; }
// example of a non-const accessor, if you REALLY want
// the caller to be able to modify m_isFull for some reason.
const bool& getIsFull() { return m_isFull; }
};
. Lastly: Learn to isolate concepts and algorithms.
A lot of the mistakes/bugs/errors in the code appear to be because you're not 100% with some of the nuances or even details. That's not unreasonable, but you need to find a way to be able to try out the little bits of the language.
Take a little time to learn to roll out micro-programs on something like ideone.com. If you are using Linux, make yourself a "srctest" directory with a "test.cpp" and "test.h" and a Makefile
Makefile
all: srctest
srctest: srctest.cpp srctestextern.cpp srctest.h
g++ -o srctest -Wall -ggdb srctest.cpp srctestextern.cpp
srctest.cpp
#include "srctest.h"
#include <iostream>
// add your other includes here and just leave them.
int main() {
return 0;
}
srctest.h
#ifndef SRCTEST_SRCTEST_H
#define SRCTEST_SRCTEST_H
// anything I want to test in a .h file here
#endif
srctestextern.cpp
#include "srctest.h"
// Anything you want to test having in a separate source file goes here.
If you're using visual studio, set yourself up something similar.
The idea is to have somewhere you can go and drop in a few lines of code and be comfortable stepping thru what you're trying in a debugger.
Being able to quickly localize problems is a key part of being a successful programmer as opposed to being an employed code monkey.
Related
I know the title sucks... but I have no clue what actual issue I have got at my hands...
I have defined a base class for linked lists and a specialized class that inherits the base class.
Base:
list.h
#ifndef LIST_H
#define LIST_H
#include <string>
#include "../../declarations.h"
#include "element.h"
class List: public Element{
/*
* #brief is a generic list class, designed to be inherited by more
* specialised list emulating classes.
*/
public: // methods
/// generates empty list.
List(){
init();
cout << "defining List" << endl;
}
/// Removes first list element
bool remove_first(){
if (!is_empty()){
Element* newFirst = first;
delete first;
first = newFirst->next;
return true;
}
else{
std::cerr << "list already empty" << endl;
return false;
}
}
/// removes last list element
bool remove_last(){
// store length fo list in min_len for switch
unsigned int min_len = 0;
if (!is_empty()){
if ((first->next) != 0){
min_len = 2;
}
else {
min_len = 1;
}
}
// as switch doesn't allow for comparisons, map any value greater
// 1 to 2 if (min_len>1) min_len = 2;
switch (min_len){
case (2):{
// Iterate over list, always look two elements ahead.
// If the next element points to 0 you have found your new last
// element (the current next to last one). Delete current-> next
// to remove the last element and let the new last one point to
// zero.
Element* current = first;
while((current->next)->next != 0){
current = (current->next);
}
delete (current->next);
current->next = 0;
return true;
}
// if the list contaisn only one element use remove_first()
// as the logic for that case is already present there
case (1): return remove_first();
case (0):{
std::cerr << "list already empty" << endl;
return false;
}
}
}
// Declare several virtual functions for appending elements
// that get defined in the iheriting classes.
virtual void append_front(int i){};
virtual void append_front(char c){};
virtual void append_front(std::string s){};
virtual void append_back(int i){};
virtual void append_back(char c){};
virtual void append_back(std::string s){};
/// todo
std::string head(){}
/// returns length of list
unsigned length(){
unsigned counter = 0;
Element* current = first;
while(current != 0) {
++counter;
current = current->next;
}
return counter;
}
/// determines whether list is empty
bool is_empty(){
return first == 0;
}
// printing depends on type of list, so this method gets defined in
// inheriting class
virtual void print(){};
private: // methods
void init(){
// initialise empty list with a NULL pointer
first = 0;
}
protected: // data members
/// points to first list element or zero, if list is empty
Element* first;
};
#endif
Derived:
transitionsList.h
#ifndef TRANSITION_LIST_H
#define TRANSITION_LIST_H
#include "../../../generic/list.h"
#include "../../elements/transition/transition.h"
class TransitionList: public List {
public:
void append_front(char c){
// generate list element and store in pointer e
Element* e;
e = new Transition();
// store parameter c in the object *e points to
e->set_content(c);
// Either list is empty. In thet case object at &e becomes first
// list element and also the last.
// Or list wasn't empty and e->next points to the current first, then
// object *e points to becomes first.
if (is_empty()) {
first = e;
e->next = 0;
}
else {
e->next = first;
first = e;
}
}
void append_back(char c){
if (is_empty()) {
append_front(c);
}
else {
Element* e;
e = new Transition();
e->set_content(c);
e->next = 0;
// Go through the list until you find the last element, let it
// then ppint to the new last element.
Element* current = first;
while(current->next != 0) {
current = current->next;
}
current->next = e;
}
}
void print(){
cout << "[";
// go through the list, starting with first element
Element* current = first;
// as long as the last list element is not the current one, keep
// printing elements.
while (current != 0) {
cout << " " << current->get_content();
// let current be the next of current current, to move
// through the list
current = current->next;
} // while
cout << " ]";
}
};
#endif
These two depend on a few other classes:
element.h:
#ifndef ELEMENT_H
#define ELEMENT_H
#include "../../declarations.h"
class State;
class Element{
/*
* #brief is a generic list element class, designed to be inherited by
* more specialised list element classes.
*/
public:
Element(){}
virtual ~Element(){}
virtual void set_content(int i){};
virtual void set_content(char c){};
virtual void set_content(std::string s){};
virtual char get_content() = 0;
Element* next; ///< is the pointer to the next transition in the list
};
#endif
state.h:
#ifndef STATE_H
#define STATE_H
#include "../../declarations.h"
class List;
class State{
/**
* #brief is a class emulating a trie state
*/
public: // methods
State(){
cout << "defining State" << endl;
init();
}
private: // methods
void init(){
}
private: // variables
// Pointer required due to forward declarations
List* transitions; ///< is the list of states dominated by THIS.
// count stores how often the word the current path codes for has been
// found in the training data.
int count; ///< is the number of occurances of some word in this path.
};
#endif
and transition.h
#ifndef TRANSITION_H
#define TRANSITION_H
#include "../../../generic/element.h"
#include "../../state.h"
typedef char cont;
class Transition: public Element {
public:
void set_content(cont c){
content = c;
};
cont get_content(){
return content;
};
State* successor;
Transition* next; ///< is the pointer to the next transition in the list
protected:
cont content; ///< is the character this transition codes for
};
#endif
When I now run this cpp-file:
list_test.cpp:
#include "transitionList.h"
int main(){
TransitionList* derivedList;
List *baseList = &derivedList;
}
I get the error:
list_test2.cpp:5:8: error: cannot initialize a variable of type 'List *' with an rvalue of type 'TransitionList **'
Which I don't understand, because I am under the (apparently phony) impression, that this would be analogous to what I saw in this tutorial:
https://youtu.be/DudHooleNVg?t=4m59s
Where is
int main(){
TransitionList* derivedList;
List *baseList = &derivedList;
}
not analogous to
int main(){
Ninja* n;
Enemy *enemy1 = &n;
}
:/ Very confused.
I've got two classes namely Family.cpp and Child.cpp. Using the instance of family I can only add a youngest child (i.e., at the end). And using the Child class I can create only an immediate younger child. This could be done by obtaining the child from the family class function Child* getChild(unsigned int i).
Family.h
#ifndef FAMILY_H_
#define FAMILY_H_
#include "Child.h"
// This is a more advanced exercise for copy and move
// constructors.
// Here there is a system of two classes and the
// copy and move should apply to the Family so as
// to create a full copy of the Family and Child.
// You can think about the main thing that is used
// by other users as the Family and the Child is
// exposed but it is going to be used only as part
// of a Family.
//
// The Family contains several children.
// The main functions that are possible to do
// to a family is to add a (youngest) child
// and to retrieve the i-th child.
// A family also supports copy and move semantics.
class Family {
public:
Family();
Family(const Family&);
~Family();
// Add a new youngest child with this name and this
// dob.
void addChild(const char* name, unsigned int dob);
// Get the i-th child of the family
Child* getChild(unsigned int) const;
// Copy and move through assignment operator
Family& operator=(const Family&);
Family& operator=(Family&&);
private:
void inline addChildren_(const Family&);
void inline reallocate_();
void inline clean_();
Child** children_;
unsigned int childrenCapacity_;
unsigned int numberOfChildren_;
};
#endif /* FAMILY_H_ */
Child.h
#ifndef CHILD_H_
#define CHILD_H_
// This is the child that should appear as part of the family.
// Each child has a name and a date of birth
// The length of the name should be unbounded
// Each child also has pointers to the (closest) older sibling and
// the (closest) younger sibling.
// If there is no such sibling, then, clearly, this pointer is nullptr.
// Each child
class Child {
public:
Child();
Child(const char* name,unsigned int dob);
~Child();
void name(char* buffer) const;
unsigned int dob() const;
Child* olderSibling() const;
Child* youngerSibling() const;
// Create a new immediate younger sibling (using dynamic memory!!!)
// If a younger sibling already exists then the new one is adopted
// and should be between the two.
// If the age order between the siblings turns out to be
// wrong the operation should fail and return null pointer.
// Notice that twins (yes, up to the millisecond) should be
// possible.
Child* addYoungerSibling(const char* name, unsigned int dob);
// Copy and move through assignment operators
Child& operator=(const Child& other);
Child& operator=(Child&&);
private:
Child* siblingOlder_;
Child* siblingYounger_;
char* childName_;
int childDob_;
void inline copyChildName_(const Child&);
void clean_();
};
#endif /* CHILD_H_ */
Family.cpp
#include "Family.h"
Family::Family() :
children_(nullptr), childrenCapacity_(0), numberOfChildren_(0) {
}
Family::~Family() {
clean_();
}
void Family::addChild(const char* name, unsigned int dob) {
if ((numberOfChildren_ > 0)
&& (children_[numberOfChildren_ - 1]->dob() >= dob)) {
return;
}
if (numberOfChildren_ == childrenCapacity_) {
reallocate_();
}
if (numberOfChildren_ == 0) {
children_[numberOfChildren_] = new Child(name, dob);
} else {
children_[numberOfChildren_] =
children_[numberOfChildren_ - 1]->addYoungerSibling(name, dob);
}
++numberOfChildren_;
}
Child* Family::getChild(unsigned int i) const {
if (i < numberOfChildren_) {
return children_[i];
}
return nullptr;
}
void Family::reallocate_() {
Child** tempChildren = new Child*[childrenCapacity_ + 5];
for (unsigned int i = 0; i < childrenCapacity_ + 5; i++) {
tempChildren[i] = (i < childrenCapacity_ ? children_[i] : nullptr);
}
if (children_) {
delete[] children_;
}
children_ = tempChildren;
childrenCapacity_ += 5;
}
Child.cpp
#include <string.h>
#include "Child.h"
Child::Child() :
siblingOlder_(nullptr), siblingYounger_(nullptr), childName_(nullptr), childDob_(
0) {
}
Child::Child(const char* name, unsigned int dob) :
siblingOlder_(nullptr), siblingYounger_(nullptr), childName_(
new char[strlen(name) + 1]), childDob_(dob) {
unsigned int i = 0;
for (; name[i]; i++) {
childName_[i] = name[i];
}
childName_[i] = 0;
}
Child::~Child() {
clean_();
}
void Child::name(char* buffer) const {
strcpy(buffer, childName_);
}
unsigned int Child::dob() const {
return childDob_;
}
Child* Child::olderSibling() const {
return siblingOlder_;
}
Child* Child::youngerSibling() const {
return siblingYounger_;
}
Child* Child::addYoungerSibling(const char* name, unsigned int dob) {
if ((!siblingYounger_) && (childDob_ < dob)) {
Child *temp = new Child(name, dob);
siblingYounger_ = temp;
temp->siblingOlder_ = this;
return temp;
} else if (siblingYounger_) {
int youngerDob = youngerSibling()->dob();
if (dob > childDob_ && dob < youngerDob) {
Child *temp = new Child(name, dob);
temp->siblingYounger_ = siblingYounger_;
temp->siblingOlder_ = this;
siblingYounger_->siblingOlder_ = temp;
siblingYounger_ = temp;
return temp;
}
}
return nullptr;
}
void Child::copyChildName_(const Child& other) {
unsigned int i = 0;
for (; other.childName_[i]; i++) {
childName_[i] = other.childName_[i];
}
childName_[i];
}
Problem:
I had the following code in main.cpp and I got the output as below which was acceptable.
Family f;
f.addChild("A", 5);
f.addChild("B", 10);
f.addChild("D", 20);
printFamily(f);
Output:
Members: A 5, B 10, D 20,
A is older than B
B is younger than A and is older than D
D is younger than B
But when I had the following code appended to main.cpp, the output was as below.
Child *childB = f.getChild(1);
Child *childC = childB->addYoungerSibling("C", 15);
printFamily(f);
Output:
Members: A 5, B 10, D 20,
A is older than B
B is younger than A and is older than C
D is younger than C
I think when I try to add a younger child, it gets added but not loaded in the family memory. How do I solve this issue?
maybe you didn't add him to the family?
not added to children_[]?
You should probably call addChild it calls addYoungerSibling...
also your in c++, use strings not chars (why strcpy when you can just return a string?)
there are all sort of things you can fix in you code. if you upload the h files it will be easier to help, if you like.
good luck
I'm am fairly new to C++.
I have this code from an assignment, i don't quite understand all of it, but i have to make the program give an option at the end for the user to recall any partnumber and model year/engine no. that was entered.
I have no idea on how to go about doing this task... maybe have some kind of id for each node so i can recall it?
Or is it my only option to rewrite the program using an array or vector data structure?
#include <iostream>
using namespace std;
typedef unsigned long ULONG;
typedef unsigned short USHORT;
// **************** Part ************
// Abstract base class of parts
class Part
{
friend void showPart();
public:
Part():itsPartNumber(1) {}
Part(ULONG PartNumber):itsPartNumber(PartNumber){}
virtual ~Part(){};
ULONG GetPartNumber() const { return itsPartNumber; }
virtual void Display() const =0; // must be overridden
private:
ULONG itsPartNumber;
};
// implementation of pure virtual function so that
// derived classes can chain up
void Part::Display() const
{
cout << "\nPart Number: " << itsPartNumber << endl;
}
// **************** Car Part ************
class CarPart : public Part
{
friend void showPart();
public:
CarPart():itsModelYear(94){}
CarPart(USHORT year, ULONG partNumber);
virtual void Display() const
{
Part::Display(); cout << "Model Year: ";
cout << itsModelYear << endl;
}
private:
USHORT itsModelYear;
};
CarPart::CarPart(USHORT year, ULONG partNumber):
itsModelYear(year),
Part(partNumber)
{}
// **************** AirPlane Part ************
class AirPlanePart : public Part
{
friend void showPart();
public:
AirPlanePart():itsEngineNumber(1){};
AirPlanePart(USHORT EngineNumber, ULONG PartNumber);
virtual void Display() const
{
Part::Display(); cout << "Engine No.: ";
cout << itsEngineNumber << endl;
}
private:
USHORT itsEngineNumber;
};
AirPlanePart::AirPlanePart(USHORT EngineNumber, ULONG PartNumber):
itsEngineNumber(EngineNumber),
Part(PartNumber)
{}
// **************** Part Node ************
class PartNode
{
public:
PartNode (Part*);
~PartNode();
void SetNext(PartNode * node) { itsNext = node; }
PartNode * GetNext() const;
Part * GetPart() const;
private:
Part *itsPart;
PartNode * itsNext;
};
// PartNode Implementations...
PartNode::PartNode(Part* pPart):
itsPart(pPart),
itsNext(0)
{}
PartNode::~PartNode()
{
delete itsPart;
itsPart = 0;
delete itsNext;
itsNext = 0;
}
// Returns NULL if no next PartNode
PartNode * PartNode::GetNext() const
{
return itsNext;
}
Part * PartNode::GetPart() const
{
if (itsPart)
return itsPart;
else
return NULL; //error
}
// **************** Part List ************
class PartsList
{
public:
PartsList();
~PartsList();
// needs copy constructor and operator equals!
Part* Find(ULONG & position, ULONG PartNumber) const;
ULONG GetCount() const { return itsCount; }
Part* GetFirst() const;
static PartsList& GetGlobalPartsList()
{
return GlobalPartsList;
}
void Insert(Part *);
void Iterate(void (Part::*f)()const) const;
Part* operator[](ULONG) const;
private:
PartNode * pHead;
ULONG itsCount;
static PartsList GlobalPartsList;
};
PartsList PartsList::GlobalPartsList;
// Implementations for Lists...
PartsList::PartsList():
pHead(0),
itsCount(0)
{}
PartsList::~PartsList()
{
delete pHead;
}
Part* PartsList::GetFirst() const
{
if (pHead)
return pHead->GetPart();
else
return NULL; // error catch here
}
Part * PartsList::operator[](ULONG offSet) const
{
PartNode* pNode = pHead;
if (!pHead)
return NULL; // error catch here
if (offSet > itsCount)
return NULL; // error
for (ULONG i=0;i<offSet; i++)
pNode = pNode->GetNext();
return pNode->GetPart();
}
Part* PartsList::Find(ULONG & position, ULONG PartNumber) const
{
PartNode * pNode = 0;
for (pNode = pHead, position = 0;
pNode!=NULL;
pNode = pNode->GetNext(), position++)
{
if (pNode->GetPart()->GetPartNumber() == PartNumber)
break;
}
if (pNode == NULL)
return NULL;
else
return pNode->GetPart();
}
void PartsList::Iterate(void (Part::*func)()const) const
{
if (!pHead)
return;
PartNode* pNode = pHead;
do
(pNode->GetPart()->*func)();
while (pNode = pNode->GetNext());
}
void PartsList::Insert(Part* pPart)
{
PartNode * pNode = new PartNode(pPart);
PartNode * pCurrent = pHead;
PartNode * pNext = 0;
ULONG New = pPart->GetPartNumber();
ULONG Next = 0;
itsCount++;
if (!pHead)
{
pHead = pNode;
return;
}
// if this one is smaller than head
// this one is the new head
if (pHead->GetPart()->GetPartNumber() > New)
{
pNode->SetNext(pHead);
pHead = pNode;
return;
}
for (;;)
{
// if there is no next, append this new one
if (!pCurrent->GetNext())
{
pCurrent->SetNext(pNode);
return;
}
// if this goes after this one and before the next
// then insert it here, otherwise get the next
pNext = pCurrent->GetNext();
Next = pNext->GetPart()->GetPartNumber();
if (Next > New)
{
pCurrent->SetNext(pNode);
pNode->SetNext(pNext);
return;
}
pCurrent = pNext;
}
}
int main()
{
PartsList pl = PartsList::GetGlobalPartsList();
Part * pPart = 0;
ULONG PartNumber;
USHORT value;
ULONG choice;
while (1)
{
cout << "(0)Quit (1)Car (2)Plane: ";
cin >> choice;
if (!choice)
break;
cout << "New PartNumber?: ";
cin >> PartNumber;
if (choice == 1)
{
cout << "Model Year?: ";
cin >> value;
pPart = new CarPart(value,PartNumber);
}
else
{
cout << "Engine Number?: ";
cin >> value;
pPart = new AirPlanePart(value,PartNumber);
}
pl.Insert(pPart);
}
void (Part::*pFunc)()const = &Part::Display;
pl.Iterate(pFunc);
cout << "\n\n\nThere are " << pl.GetCount() << " items in the list" << endl;
return 0;
}
I tried using The Find() in the PartsList class. Does Find() take the partnumber and return the address of the part?
I wrote this to dereference the retrieved address, but it gives me the error no match for 'operator<<' in 'std::cout << * show':
int findnumber;
ULONG position;
cout << "Enter Partnumber" << endl;
cin >> findnumber;
Part* show = pl.Find(position, findnumber);
cout << *show;
Am i doing this all wrong? D: Show me please...
The function Find does take a part number, but returns a pointer to a part, which is not the same as the address of the part (that would be a reference, denoted by an &). In addition, Find takes a reference to a variable called 'position', so after calling the Find function, the variable that was passed in for 'position' will contain the value of where the part is in the linked list.
The reason you can't use the << operator, is that it hasn't been provided for the Part class. However, from the source code provided, it looks like the objective is for you to understand Polymorphism and rather than trying to use <<, call the Display function on the part that you have found. e.g: -
Part* part = pl.Find(position, findnumber);
part->Display();
This will display the text for the relevant type of part, so if the part returned was a CarPart, the CarPart's Display function will be called, whereas if the part is an AirPlane part, its Display function is called.
If you wanted to use the stream operator (<<) you'd need to overload the io operators, which you can read more about here.
The class PartsList already has a Find() method that could be used to retrieve any part based on its partnumber. You can then call the Display() method of that part.
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.
This code works if the 7th line down says "typedef char ItemType" but instead I made it typedef to the EventInfo object. The MSVS compiler says some really weird things...
error C2146: syntax error : missing ';' before identifier 'ItemType'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
But I don't understand why it works correctly when it is a char.
I know this is a lot of code but the typedef is on the 7th line. I included the whole thing because I don't know what to expect.
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
const int MaxQueueSize = 8; // Queue Struct can hold up to 8
typedef EventInfo ItemType; // the queue's data type !DOES NOT COMPILE
enum EventType {Arrival, Depart};
class EventInfo
{
public:
EventInfo() : eTime(0), aTime(0), minutes(0) {}
int eventTime();
int duration();
void ScheduleEvent(int eTime, int duration);
bool compare(int eTime);
private:
int eTime; //either the arrival time of the next customer or the departure time of the customer currently at the teller window
int aTime; //either the service time for the arriving customer or the wait time for the customer at the teller window
float minutes;
};
int EventInfo::eventTime()
{
return this->eTime;
}
int EventInfo::duration()
{
return this->aTime;
}
void EventInfo::ScheduleEvent(int eTime, int duration)
{
this->eTime = eTime;
this->aTime = duration;
}
bool EventInfo::compare(int eTime)
{
return (eTime == this->eTime);
}
///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////
////////////////
class CPPQueue
{
public:
CPPQueue() : front(0), rear(0), count(0) { };
ItemType item[MaxQueueSize];
bool IsEmpty() const;
bool IsFull() const;
void Enqueue(ItemType newItem);
void PrintQ();
void PrintQueueInfo();
ItemType Dequeue();
int Count();
private:
int front, rear;
int count;
};
bool CPPQueue::IsEmpty() const
{
return (this->count == 0);
}
bool CPPQueue::IsFull() const
{
return (this->count == MaxQueueSize);
}
void CPPQueue::Enqueue(ItemType newItem)
{
if(this->count == MaxQueueSize)
{
cerr << "Error! Queue is full, cannot enqueue item.\n" << endl;
exit(1);
}
this->item[this->rear] = newItem;
this->rear++;
if (this->rear == MaxQueueSize)
{
this->rear = 0; // adjustment for circular queue
}
this->count++;
}
ItemType CPPQueue::Dequeue()
{
ItemType theItem;
if(this->count == 0)
{
cerr << "Error! Queue is empty, cannot dequeue item.\n" << endl;
exit(1);
}
theItem = this->item[this->front ];
this->front++;
if (this->front == MaxQueueSize)
{
this->front = 0; // adjustment for circular queue
}
this->count--;
return theItem;
}
// Function PrintQ() prints the contents of the queue without changing
// the queue. Printing starts at the "front" index and stops before we
// get to the "rear" index. A decrementing counter controls the loop.
//
void CPPQueue::PrintQ()
{
int i;
int qindex = this->front;
for(i = this->count; i > 0; i--)
{
cout << this->item[qindex] ;
qindex = (++qindex) % MaxQueueSize; // adjustment for circular queue
if(i > 1)
cout << ", ";
}
}
// Helper function for the main program below.
void CPPQueue::PrintQueueInfo()
{
cout << "The queue contains: ";
PrintQ();
cout << endl;
}
int CPPQueue::Count()
{
return this->count;
}
enum TellerStatus {Idle, Busy};
class Teller
{
public:
Teller() : status(Idle), idleTime(0), totalIdleTime(0) {}
void changeStatus(TellerStatus status);
TellerStatus getStatus(void);
private:
TellerStatus status;
int idleTime; //!
int totalIdleTime; //!!
};
void Teller::changeStatus(TellerStatus status)
{
this->status = status;
}
TellerStatus Teller::getStatus()
{
return this->status;
}
class Bank
{
public:
Bank() : Clock(0.0) {}
void RunSimulation();
private:
EventInfo Event[2]; // array of two events - next arrival and next departure
CPPQueue WaitLine; // the customer wait line [with max size = 8]
float Clock; // to keep track of Current Bank Time
Teller theTeller; // the single teller in the bank
ifstream myfile;
void ProcessArrival(), ProcessDeparture(), PrintHeader(), PrintReportLine(), PrintStatsReport();
};
void Bank::RunSimulation()
{
}
void Bank::ProcessArrival()
{
int a, b;
string filename, x;
filename = "P3Data1.txt";
myfile.open(filename);
while (myfile >> a >> b)
{
Event[1].ScheduleEvent(a, b);
WaitLine.Enqueue(Event);
}
}
int main()
{
Bank myBank;
myBank.RunSimulation();
}
The name EventInfo is only usable from its point of declaration forward. Your typedef is too early, and the compiler doesn't yet know what a EventInfo is.
You can move the typedef below the class definition, or you can tell the compiler that EventInfo is a class:
typedef class EventInfo ItemType;
In C++, unlike in Java, you can only use names that have been declared earlier in the file. So just change the order:
class EventInfo { /* ... */ };
typedef EventInfo ItemType;
In fact, it's enough to just declare the class, if you don't want to define it just yet: class EventInfo;
Put the typedef after the class definition. You can't do typedef for unknown types.
First you need to forward declare class EventInfo;
Otherwise your typedef has no idea of what EventInfo is.
THen you have various problems, e.g. you need to overload << for EventInfo class etc.