I'm currently working on a LinkedList project for school. I'm trying to get VScode to work properly, but I keep getting this linker error when building. I've had to use Xcode to build and test since I don't get a linker error in that environment. My project includes main.cpp, LinkList.h/.cpp, Node.h/.cpp, and Player.h/.cpp.
Here is my error code:
Starting build...
/usr/bin/g++ -fdiagnostics-color=always -g "/Users/Daniel/Desktop/School/CS 2337/Project 2/Project2/main.cpp" -o "/Users/Daniel/Desktop/School/CS 2337/Project 2/Project2/main"
Undefined symbols for architecture arm64:
"Node::Node(Player*)", referenced from:
_main in main-37fea9.o
"Player::Player(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in main-37fea9.o
"LinkList::addNode(Node*)", referenced from:
_main in main-37fea9.o
"LinkList::LinkList()", referenced from:
_main in main-37fea9.o
"LinkList::~LinkList()", referenced from:
_main in main-37fea9.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Code for main:
#include <iostream>
#include <fstream>
#include <string>
#include "LinkedList/LinkList.h"
#include "Node/Node.h"
#include "Player/Player.h"
using namespace std;
void displayStats(LinkList &players);
int main()
{
LinkList players;
string filename;
cout << "What's input file name? ";
cin >> filename;
ifstream file;
file.open(filename);
string line = "", name = "", record = "";
while(getline(file,line))
{
name = line.substr(0, line.find(' '));
record = line.substr(line.find(' ') + 1);
Player *tempPlayer = new Player(name, record);
Node *tempNode = new Node(tempPlayer);
players.addNode(tempNode);
}
file.close();
displayStats(players);
//findLeaders(players);
//displayLeaders(players);
}
//---------TESTING FUNCTION---------//
//void test()
//{
//
//}
void displayStats(LinkList &players)
{
cout << players << endl;
}
Code for LinkList.h:
#ifndef LINKLIST_H
#define LINKLIST_H
#include "../Node/Node.h"
#include <string>
//TODO: Sort method
using namespace std;
//template <typename Type>
class LinkList
{
public:
Node* head; //are the the brackets needed?
Node* tail;
//--------Constructors & Destructors--------//
LinkList();
LinkList(Node*);
~LinkList();
void Sort();
void addNode(Node *node);
Node* exists(Node *node);
void ToString();
void getSize();
//-----Overloaded Operator---------//
Node operator[](int index);
friend ostream& operator<<(ostream& out, const LinkList &obj)
{
Node* curr = obj.head;
while(curr != nullptr)
{
out << *(curr->object) << endl;
curr = curr->next;
}
return out;
}
friend istream& operator>>(istream&, LinkList &obj);
// private:
// protected:
};
#endif //LINKLIST_H
Code for LinkList.cpp:
#include "LinkList.h"
#include <iostream>
using namespace std;
//------Constructors-------//
LinkList::LinkList()
{
head = nullptr;
tail = nullptr;
}
LinkList::LinkList(Node* head)
{
this->head = head;
this->tail = head;
Node* curr = head->next;
while(curr != nullptr)
{
this->tail = curr;
curr = curr->next;
}
}
//--------Destructors---------//
LinkList::~LinkList()
{
Node* prev = head, *curr = head;
while(curr != nullptr)
{
curr = curr->next;
delete prev;
prev = curr;
}
}
//--------Miscellaneous=--------//
Node* LinkList::exists(Node *node)
{
Node* curr = this->head;
while(curr != nullptr)
{
if(curr->object->getName() == node->object->getName())
{
return curr;
}
curr = curr->next;
}
return nullptr;
}
void LinkList::addNode(Node *node)
{
Node* existingNode = exists(node);
if(head == nullptr)
{
head = node;
tail = node;
}
else if(existingNode)
{
*existingNode += *node;
}
else
{
tail->next = node;
tail = node;
}
}
//--------Overloaded Operators-----------//
Code for Node.h:
#ifndef NODE_H
#define NODE_H
#include <string>
#include "../Player/Player.h"
using namespace std;
//template<typename Type>
class Node
{
public:
Player* object;
Node* next;
//-------Constructors & Destructors-------//
Node();
Node(Player *object);
Node(const Node &obj);
~Node();
//------Overloaded Operators-----------//
bool operator==(const Node &right);
bool operator>(const Node &right);
bool operator<<(const Node &right);
Node& operator=(const Node &obj);
void operator+=(Node &obj);
private:
protected:
};
#endif //NODE_H
Code for Node.cpp:
#include "Node.h"
#include "../Player/Player.h"
#include <iostream>
using namespace std;
//-------Constructors & Destructors-------//
Node::Node()
{
object = nullptr;
next = nullptr;
}
Node::Node(Player *object)
{
this->object = object;
next = nullptr;
}
Node::Node(const Node &obj)
{
this->object = obj.object;
this->next = obj.next;
}
Node::~Node()
{
//destructor
}
//-----Overloaded Operators-------//
void Node::operator+=(Node &obj)
{
this->object->setAt_Bats(
this->object->getAt_Bats() + obj.object->getAt_Bats());
this->object->setHits(
this->object->getHits() + obj.object->getHits());
this->object->setWalks(
this->object->getWalks() + obj.object->getWalks());
this->object->setStrikeouts(
this->object->getStrikeouts() + obj.object->getStrikeouts());
this->object->setOuts(
this->object->getOuts() + obj.object->getOuts());
this->object->setHits_By_Pitch(
this->object->getHits_By_Pitch() + obj.object->getHits_By_Pitch());
this->object->setSacrifices(
this->object->getSacrifices() + obj.object->getSacrifices());
this->object->setPlate_Appearances(
this->object->getPlate_Appearances() + obj.object->getPlate_Appearances());
}
Code for Player.h:
#ifndef PLAYER_H
#define PLAYER_H
#include <string>
#include <cmath>
#include <iostream>
#include <iomanip>
using namespace std;
class Player
{
public:
//---------Constructors & Destructors--------//
Player();
Player(string);
Player(string, string);
~Player();
Player(const Player &obj);
//---------Accessors & Mutators---------//
string getName() {return name;}
void setName(string n) {name = n;}
int getAt_Bats() {return at_bats;}
void setAt_Bats(int num) {at_bats = num;}
int getHits() {return hits;}
void setHits(int num) {hits = num;}
int getWalks() {return walks;}
void setWalks(int num) {walks = num;}
int getStrikeouts() {return strikeouts;}
void setStrikeouts(int num) {strikeouts = num;}
int getOuts() {return outs;}
void setOuts(int num) {outs = num;}
int getHits_By_Pitch() {return hits_by_pitch;}
void setHits_By_Pitch(int num) {hits_by_pitch = num;}
int getSacrifices() {return sacrifices;}
void setSacrifices(int num) {sacrifices = num;}
int getPlate_Appearances() {return plate_appearances;}
void setPlate_Appearances(int num) {plate_appearances = num;}
//-----------Calculators------------//
double calcBA()
{
if(at_bats == 0) return 0;
return (double)hits/at_bats;
}
double calcOB()
{
if(plate_appearances == 0) return 0;
return ((double)(hits + walks + hits_by_pitch)/(double)plate_appearances);
}
//----------Overloaded Operators----------//
bool operator==(Player &right);
bool operator>(Player &right);
bool operator<(Player &right);
Player& operator=(const Player &obj);
friend ostream& operator<<(ostream&, const Player &obj);
friend ostream& operator<<(ostream& out, Player &obj)
{
out << obj.getName() << "\t";
out << obj.getAt_Bats() << "\t";
out << obj.getHits() << "\t";
out << obj.getWalks() << "\t";
out << obj.getStrikeouts() << "\t";
out << obj.getHits_By_Pitch() << "\t";
out << obj.getSacrifices() << "\t";
out << fixed << setprecision(3) << obj.calcBA() << "\t";
out << fixed << setprecision(3) << obj.calcOB() << endl;
return out;
}
friend istream& operator>>(istream&, Player &obj);
private:
string name;
int at_bats, hits, walks, strikeouts, outs, hits_by_pitch, sacrifices, plate_appearances;
void sortRecord(string);
protected:
};
#endif //PLAYER_H
Code for Player.cpp:
#include "Player.h"
#include <iostream>
using namespace std;
//----------Constructors--------//
Player::Player()
{
name = "";
at_bats = 0;
hits = 0;
walks = 0;
strikeouts = 0;
outs = 0;
hits_by_pitch = 0;
sacrifices = 0;
plate_appearances = 0;
}
Player::Player(string x)
{
name = x;
}
Player::Player(string name, string recordLine)
{
this->name = name;
at_bats = 0;
hits = 0;
walks = 0;
strikeouts = 0;
outs = 0;
hits_by_pitch = 0;
sacrifices = 0;
plate_appearances = 0;
sortRecord(recordLine);
}
Player::Player(const Player &obj)
{
this->name = obj.name;
this->at_bats = obj.at_bats;
this->hits = obj.hits;
this->walks = obj.walks;
this->strikeouts = obj.strikeouts;
this->outs = obj.outs;
this->hits_by_pitch = obj.hits_by_pitch;
this->sacrifices = obj.sacrifices;
this->plate_appearances = obj.plate_appearances;
}
//---------Destructor--------//
Player::~Player()
{
//run destructor
}
//----------Miscellaneous--------//
void Player::sortRecord(string record)
{
bool invalid = false;
bool atbat = false;
for(char x : record)
{
switch (x)
{
case 'H':
this->hits++;
atbat = true;
break;
case 'O':
this->outs++;
atbat = true;
break;
case 'K':
this->strikeouts++;
atbat = true;
break;
case 'W':
this->walks++;
break;
case 'P':
this->hits_by_pitch++;
break;
case 'S':
this->sacrifices++;
break;
default:
invalid = true;
break;
}
if(!invalid) this->plate_appearances++;
if(atbat) this->at_bats++;
atbat = false;
invalid = false;
}
}
//-------Overloaded Operators---------//
Player& Player::operator=(const Player &obj)
{
this->name = obj.name;
this->at_bats = obj.at_bats;
this->hits = obj.hits;
this->walks = obj.walks;
this->strikeouts = obj.strikeouts;
this->outs = obj.outs;
this->hits_by_pitch = obj.hits_by_pitch;
this->sacrifices = obj.sacrifices;
this->plate_appearances = obj.plate_appearances;
return *this;
}
I know this is a lot, but any help would be greatly appreciated. Let me know if you guys need anything else and I would be glad to provide it.