0

I have a linked list class that uses templates for both the Node class and the List class. I've done some debugging and come to the conclusion that in my Node class, the member functions cannot access the member data, but the constructors can. I would like to know how i can fix this!

#include <iostream>
#include <fstream>
#include <string>
#include "List.h"


using namespace std;


int main()
{
ifstream fileIn("data1.txt");

List<int> studentList;

if(fileIn.fail())
    cout << "file did not open" << endl;
else

    studentList.add(fileIn);




fileIn.close();
cin.get();
cin.ignore();
return 0;

}

//List.h //ignore the commented methods, have yet to write them.

#ifndef LIST_H
#define LIST_H

#include <cstdlib>
#include <iostream>
#include <fstream>
#include "Node.h"

using namespace std;

template <class NumType>
class List
{  

int counter;

bool isEmpty();
const bool print(){
}

public:

Node<NumType> * head;

    List()
    {

        this->head = NULL;
        counter = 0;
    }

    ~List()
    {

    }


    //place in an order thart keeps the array in ascending order
    void add(ifstream &);
/*  
    Node* location(Node *){
    }

    bool remove(const int){
    }

    bool clear(){
    }

    const void peek(const Node*){
    }

    //average of all test scores or just one students test scores?
    float average(){
    }

    char grade(){
    }
*/
};



#include "List.cpp"
#endif

//List.cpp

#include "List.h"


using namespace std;

template <class NumType>
bool List<NumType> :: isEmpty()
{
cout << "inside isEmpty" << endl;
return(head == NULL);
}


template <class NumType>
void List<NumType> :: add(ifstream & fin)
{   int dummyID;
NumType tests[3];
string dummyName;


while(fin >> dummyID)
{       fin.ignore();
        getline(fin, dummyName);

        for(int x = 0; x < 3; x++)
            fin >> tests[x];
        fin.ignore();

        cout << dummyID << endl;
        cout <<dummyName << endl;
        for(int y = 0; y < 3; y++)
            cout << tests[y] << " ";

    if(isEmpty())
    {   

        this->head = new Node<NumType>(NULL, tests, dummyID, dummyName);
        counter++;cout << "inside" << endl;
    }
    else 
    {
        Node<NumType> *newNode = new Node<NumType>(NULL, tests, dummyID,    dummyName);



        Node<NumType> *first = new Node<NumType>(NULL, tests, dummyID, dummyName);
        Node<NumType> *second;

        first = this->head;
        second = this->head->getNext();

        //create location() method to handle this!
        for(int x = 0; x < counter; x++)
        {           

                if(first->getID() > newNode->getID())
                {
                    head = newNode;

                    counter++;
                    break;  
                }
                else if(first->getID() < newNode->getID() && second->getID() > newNode->getID())
                {

                    newNode->setNext(second);
                    first->setNext(newNode);

                    counter++;
                    break;
                }
                else if(second->getID() < newNode->getID() && second->getNext() == NULL)
                {
                    second->setNext(newNode);

                    counter++;
                    break; 
                }
                else
                {
                    first = second;
                    second = second->getNext();
                }
        }

    }
}
Node<NumType> * temp = head;
for(int x = 0; x <= counter; x++)
{
    NumType *arr;

    cout << temp->getID() << endl << temp->getName() << endl;
    arr = temp->getAllScores();
    for(int y = 0; y <3 ; y++)
        cout << *(arr+y) << endl;

    temp = temp->getNext();
}

}

//Node.h

#ifndef NODE_H
#define NODE_H


#include <cstdlib>
#include <iostream>

using namespace std;

template <class ItemType>
class Node
{

    static const int SIZE = 3;
    int ID;
    ItemType scores[SIZE];
    string name;
    Node *next;



public:

    Node()
    {
        this->scores[0] = 0;
        this->scores[1] = 0;
        this->scores[2] = 0;
        this->name = "";
        this->ID = 0;
        this->next = NULL;  
    }


    Node(Node * nPtr, ItemType tests[], int num, string n)
    {
        this->next = nPtr;

        for(int z = 0; z < SIZE; z++)
            this->scores[z] = tests[z];

        this->ID = num;
        this->name = n;
    }

    ~Node(){}


    void setNext( Node * );

    string getName();

    int getID();


    ItemType* getAllScores();

    Node* getNext();




};

#include "Node.cpp"
#endif

Node.cpp

#include "Node.h"
#include <string>

using namespace std;


template <class ItemType>
void Node<ItemType> :: setNext( Node * nextPtr)
    {
        cout << "inside setNext()" << endl;
        this->next = nextPtr;
        cout << "exited setNext()" << endl;
    }

    template <class ItemType>
    string Node<ItemType> :: getName()
    {
        return (this->name);
    }

    template <class ItemType>
    int Node<ItemType> :: getID()
    {
        return (this->ID);  
    }

    template <class ItemType>
    ItemType* Node<ItemType> :: getAllScores()
    {
        return (this->scores);
    }

    template <class ItemType>
    Node<ItemType> * Node<ItemType> :: getNext()
    {
        return (this->next);
    }
  • Not sure this is exactly what you are dealing with, but give this a read: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file Whether it solves your immediate problem or not, it will solve a lot of future problems. – user4581301 Apr 29 '16 at 23:29
  • Now that I've read through the code, there are too many reasons this code isn't going to work to resolve here. Instead I'm going to make a few suggestions. The list knows to much about what it contains. This makes it really hard to tell whether a bug is in the list logic or in the data in and processing logic, especially considering that the list is a template. Split the two up. Write the linked list on it's own. Test the crap out of it so you know you can add, remove, find and walk through it without error. Then write separate, new class that reads and holds file data. – user4581301 Apr 29 '16 at 23:56

1 Answers1

0

I think I found the error. The first time you run the add method head is set, but the second time you are trying to set the second value. You have this code

first = this->head;// this is the first element
second = this->head->getNext(); // this is null (hast been assign yet

then you go inside of a for loop, and in the first "else if" statement you have this:

else if(first->getID() < newNode->getID() && second->getID() > newNode->getID())

when you say second->getID() you are saying null->getID() causing you a segmentation fault.

I hope this fixes your problem. Good luck!

Felipe Centeno
  • 2,911
  • 1
  • 21
  • 39