0

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.

0 Answers0