PersonC
PersonC

Reputation: 105

Linked List printing only last element in C

I'm suppose to implement QuickSort on a linked list, but I'm having trouble reading from text file into the list and printing all the nodes. I only get the last element printed as Output. What am I doing wrong?

My text file looks like this (password and its usage frequency):

asdfgh 31554
snoopy1 15637
qwertyuiop 24372
soccer 21208
.
.

Here's my structs

struct list_element {
char *password;
int count;
list_element* next;
};

struct list {
list_element* first;
list_element* last;
};

ReadfromData()

void read_data(char* filename, list* mylist)
{

FILE *fp;

char password[128];
int freq;

fp = fopen(filename, "r");

if(fp == NULL)
{
 perror("Error opening file");
 return;
}


while(fgets(password, sizeof(password), fp))
{

 list_element *node = malloc(sizeof(list_element));

 char *token;
 token = strtok(password, " ");
 node->password = strdup(token);

 if( token != NULL ){
 token = strtok(NULL, " ");
 }

 freq = atoi(token);
 node->count = freq;
 node->next = NULL;

 insert_list(node, mylist);
 }

 fclose(fp);
}

Insert infront in List

void insert_list(list_element* le, list* mylist)

if((mylist->first = NULL)){
mylist->first = le;
}else{
le->next = mylist->first;
mylist->first = le;
} 

Print list

void print_list(list* mylist)

list_element *temp;
temp = mylist->first;

while(temp != NULL)
{
printf("pass %s and count %d \n", temp->password, temp->count);
temp = temp->next;
}

I've also wrote a small function, which I call in the beginning of the program to intailize the list:

void init_list(list* mylist){
mylist = (list*)malloc(sizeof(list));
mylist->first = mylist->last = NULL;
}

but I don't think it makes sense to do a malloc here too, since I already create node one by one, right? Confused abit.

Any advice would be great!

Upvotes: 0

Views: 1414

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409482

Lets take a closer look at the init_list function:

void init_list(list* mylist){
mylist = (list*)malloc(sizeof(list));
mylist->first = mylist->last = NULL;
}

The argument mylist is a local variable. And as such it will go out of scope when the function ends and all changes to it will be lost. Because of this the pointer you will be using after the call to init_list will not actually be initialized and you will have undefined behavior when you use it.

There are two solutions: Either have init_list take no argument and instead return the new list. Or you emulate pass by value by passing a pointer to the list variable from the calling function, meaning the init_list function takes a pointer to a pointer to the structure.

The second alternative could look like this

void init_list(list **mylist)
{
    *mylist = malloc(sizeof **mylist);
    (*mylist)->first = (*mylist)->last = NULL;
}

Then you call it using the address-of operator:

list *mylist;
init_list(&mylist);

Upvotes: 1

Related Questions