Reputation: 303
Why does my linked list print only last two elements instead of complete list? I have four nodes in the list, but print only the last two.
Expected: 10--->20--->30--->40
Actual: 30-->40
struct node
{
int data;
struct node *next;
};
struct node *head=NULL;
void add(struct node **head, int d)
{
struct node **p;
p = head;
struct node *t = malloc(sizeof(struct node));
t -> data = d;
t -> next = NULL;
if(*p==NULL)
{
*p = t;
}else{
while((*p)->next !=NULL)
{
(*p) = (*p) -> next;
}
(*p) -> next = t;
}
}
void print(struct node *head)
{
struct node *t;
t = head;
while(t!=NULL)
{
printf("%d", t->data);
t = t -> next;
}
}
main()
{
add(&head,10);
add(&head,20);
add(&head,30);
add(&head,40);
print(head);
}
Upvotes: 0
Views: 49
Reputation: 66194
This is wrong:
(*p) = (*p) -> next;
This says "set the value of the pointer addressed by the pointer-to-pointer p
to the value of the node currently addressed by said-same's next
member." This has all the appearances of cookie-cutting code without understanding what it does.
The proper form to do this, which removes the special case of testing for a null head as a bonus, should look like this:
void add(struct node **pp, int d)
{
while (*pp)
pp= &(*pp)->next;
*pp= malloc( sizeof **pp);
if (*pp)
{
(*pp)->data = d;
(*pp)->next = NULL;
}
else
{
perror("Failed to expand linked list");
exit(EXIT_FAILURE);
}
}
The pp
pointer-to-pointer in this function initially addresses the head pointer back in the caller. If the list is empty that pointer will be null, and thus *pp
here will be null. Therefore the while-loop will self-terminate immediately. Otherwise it will walk the list, each time adjusting pp
(not *pp
) to hold the address of the next
member of whatever node it currently refers. This effectively follows a chain of pointers. Remember, pp
holds the address of a pointer to node, not the address of a node. When it lands on the last pointer in the list (the last next
member in the last node) it will contain the address of that next
, which is pointing to NULL. From there, the new node can be hung and we're done.
Upvotes: 1
Reputation: 32732
The problem isn't in the printing, it is in the adding.
You successfully add the first two nodes. When you add the third, (*p)->next
is not NULL, so you execute the body of the while loop, (*p) = (*p)->next;
. This will overwrite *head
with, leaking the first node and reducing you list to having only one node (the second one you added). Then the new node is added after that node, resulting in the list again having two nodes. This continues when adding other nodes.
To fix this, you don't want to write to *p
except in the case that the list is empty. In that case, though, you can use *head = t;
. This allows changing the type of p
from struct node **
to a single pointer, struct node *p
. Initialize it with *head
, then all the reads/writes to (*p)
will just be p
.
Upvotes: 0