Question

I have written a set of functions which together build a list of "Hubs" from a .csv file. I wish to generate a linked-list of these hubs in my main function I have a "head" pointer that I can pass to other functions in main.

The code in main:

HubNode *hh = NULL;
HubNode **head;
*head = hh;
Tools::loadHubs(head); 
cout << hh->name; /* HubNodes have a string called "name" */

The code in Tools:

void Tools::loadHubs(HubNode **head)
{
  string line, name, location;
//  headFlights = currFlights = prevFlights = NULL;

  ifstream myfile("Hub.csv");
  if (myfile.is_open())
  {
    while (getline(myfile, line)) {// Omit the Caption Line.
      while (getline(myfile, name, ','))//Get every value in order.
      {
        getline(myfile, location, '\n');
//        cout << line << "\n";
//        cout << name << "\n";
//        cout << location << "\n";
        HubNode::AddHub(name, location, head);
      }
    }
    myfile.close();
  }
  else { cout << "\nUnable to open file\n"; }
}

The code in HubNode:

void HubNode::AddHub(string sname, string slocation, HubNode **head)
{
  HubNode* newNode = new HubNode;
  HubNode *point;

  newNode->next = NULL;
  newNode->name = sname;
  newNode->location = slocation;

  if (*head != NULL)
  {
    HubNode *curr = *head;
    while (curr->next != NULL)
    {
      curr = curr->next;
    }
    curr->next = newNode;
  }
  else
  {
    point = newNode;
    *head = point;
  }
}

I thought that using a double pointer to the head of the list in this way would work, so that from "hh" in main, I would have access to the whole linked-list.

When I compile and start debugging, I can see that AddHubs is successfully creating the HubNodes in its scope, But when I try to access any of the elements from main (e.g. by cout << hh->name), I get a segmentation fault.

What have I done wrong? (Let me know if I need to post more code...)

Was it helpful?

Solution

You wouldn't do this:

int value = 10;
int *p;
*p = value;

So why would you think this would work:

HubNode *hh = NULL;
HubNode **head;
*head = hh;

The indirection is the same, only the type has changed. And both snippets invoke undefined behavior. This code should do this:

HubNode *hh = NULL;
Tools::loadHubs(&hh); 
cout << hh->name;

Further, your add function should be:

void HubNode::AddHub(const string& sname, const string& slocation, HubNode **head)
{
  HubNode* newNode = new HubNode;
  newNode->next = NULL;
  newNode->name = sname;
  newNode->location = slocation;

  while (*head)
      head = &(*head)->next;

  *head = newNode;
}

It gets even more straight forward if you provide a proper constructor for HubNode that takes the sname and slocation as construction parameters and initializes the node next member to NULL. if you code that, the add becomes simply:

void HubNode::AddHub(const string& sname, const string& slocation, HubNode **head)
{
  while (*head)
      head = &(*head)->next;
  *head = new HubNode(sname, slocation);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top