Why I can't traverse this linked list in C? - c

I'm having a hard time to understand why I'm having an infinite loop while I try to traverse a linked list I made to practice :
#include <stdio.h>
#include <stdlib.h>
typedef struct noeud {
int val;
struct noeud *next;
} noeud;
noeud* add_first(noeud* head, int val){
noeud* p = malloc(sizeof(noeud));
if(p == NULL){
puts("ERROR ALLOCATING NODE ");
exit(-1);
}
else{
p->val = val;
p->next = head;
}
return p;
}
void discover(noeud* head){
noeud* current = head;
while(current != NULL){
printf("---|%d|-|%p|---",current->val, current->next);
current = head->next;
}
}
int main(){
noeud* head = malloc(sizeof(noeud));
head->next = NULL;
head = add_first(head, 5);
head = add_first(head, 4);
head = add_first(head, 3);
head = add_first(head, 8);
discover(head);
return 0;
}
Here's what I did : I created a function like push to add nodes at first, each one will link to the previous one, I'm updating head to take the first node each time I push something new .
Then I'm just trying to print the result and the adresse of the next node, to do so, I used a while loop and I would verify for the NULL condition, I believe the problem is that after updating head, then head->next is not NULL anymore, but I can't really find a way to keep the last element point to null .

In the beginning of your function, you copied the head pointer to a stack variable, noeud* current = head;, but then inside the while loop you assign the stack variable to the next member of head, current = head->next;.
This will just lead to continuous assignment to the same next address and never moves current just switch it to this:
current = current->next;

It looks strange how you allocate memory for a "head node", you don't need to do that. All you need is a single HEAD pointer like so noeud* head = NULL;.
Your main() becomes:
int main(){
noeud* head = NULL;
head = add_first(head, 5);
head = add_first(head, 4);
head = add_first(head, 3);
head = add_first(head, 8);
discover(head);
return 0;
}
Then you have to modify your printing function as per the Josh Weinstein answer:
void discover(noeud* head){
noeud* current = head;
while(current != NULL){
printf("---|%d|-|%p|---\n",current->val, current->next);
current = current->next;
}
}

Related

create linked list using char array as data

I am having a problem on assigning char array after I create a node.
I am having trouble on this function I created which it would make a new node and then assign character array into the created node. I don't have any problems when it comes to int but I can't seem to run when I switched to character array.
I get a run time error when I try to run my code.
Any help would be much appreciated.
Thank You!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct node{
char data[MAX];
struct node *next;
};
typedef struct node* nodePtr;
void create(nodePtr head, char data[]);
int main()
{
nodePtr head = NULL;
char str[] = "HELLO";
create(head, str);
return 0;
}
void create(nodePtr head, char data[])
{
if (head == NULL)
{
// empty list
head = (nodePtr) malloc(sizeof(struct node)); // create root
strcpy(head->data, data);
head->next = NULL;
}
else
{ // list not empty
nodePtr current = head; // start at the beginning...
while (current->next != NULL)
{
current = current->next; // walk to the end of the list
}
current->next = (nodePtr) malloc(sizeof(struct node));
current = current->next;
strcpy(current->data, data);
}
}
There is more than one problem with your program.
To begin with, when you add elements to a list that already has a head, are not initializing the next member. This will cause multiple list insertions to fail.
current->next = malloc(sizeof(struct node));
current = current->next;
strcpy(current->data, data);
current->next = NULL; //<-- you forgot this
The other big issue is that you are also leaking your entire list, because you pass the head pointer by value into the function. When the list is empty, the function modifies this value but it's a copy so when the function returns, the value of head in main is still NULL.
There are two options. Either you change your function to expect a pointer to the head-pointer, or you use what's called a "dummy head".
Using a dummy head actually simplifies lists a lot. What this means is your head is actually an unused node whose sole responsibility is to store the actual head in its next-pointer:
struct node head = {}; // dummy head node
create(&head, str);
The above will never actually hit the head == NULL part of the create function because dummy heads guarantee the head is always a valid node. So if you set your list up that way, then your create function can be simplified.
If you don't want to do this, then you need to pass a pointer to your head pointer. That means your create function becomes:
void create(nodePtr *head, char data[])
{
if (*head == NULL)
{
*head = malloc(sizeof(struct node));
strcpy((*head)->data, data);
(*head)->next = NULL;
}
else
{
nodePtr current = *head;
while (current->next != NULL) current = current->next;
current->next = malloc(sizeof(struct node));
current = current->next;
if (current != NULL)
{
strcpy(current->data, data);
current->next = NULL;
}
}
}
And you would invoke the above as:
nodePtr head = NULL;
create(&head, str);
One extra thing you might wish to do is make the function return the node that it created. The reason you might want to do this is that currently if you're inserting many items into the list you have to search to the end every time. If instead you pass the last node as the next head, then no searching is necessary:
nodePtr head = NULL;
nodePtr tail = head;
tail = create(head, "goodbye");
tail = create(tail, "cruel");
tail = create(tail, "world");
This would mean a small modification to your function, but I'm sure you can work that out.

Why does a linked list with a double pointer cause an error?

I'm asking you a question because the assignment I was doing didn't work out.
The structure is a common link list, declaring the head pointer in the main and passing the address value of the head pointer as a parameter to the function.
The global variable top is used to determine where the current data is located.
The code currently below will detect only errors when executed.
Structure:
struct ListNode{
int data;
struct ListNode* link;
};
int top = 0;
code:
void DisplayList(ListNode** head){
if(*head == NULL){
printf("List = Empty\n");
}
else{
printf("List = ");
for(;(*head) != NULL; *head = (*head)->link){
printf("%d ",(*head)->data);
}
}
printf("\n");
}
void AddList(ListNode** head){
ListNode* temp = (ListNode*)malloc(sizeof(ListNode));
int num;
printf("Data register) ");
scanf("%d",&num);
temp->data = num;
temp->link = NULL;
top++;
if(*head == NULL){
*head = temp;
}
else{
for(;(*head)->link != NULL; *head = (*head)->link){}
(*head)->link = temp;
}
DisplayList(head);
}
the expected result:
Data register) 10
List = 10
Data register) 20
List = 10 20
Data register) 30
List = 10 20 30
You shouldn't modify *head in the loops. You need to use a local variable to step through the list, otherwise you're changing the caller's variable to point to the end of the list.
void DisplayList(ListNode** head){
if(*head == NULL){
printf("List = Empty\n");
}
else{
printf("List = ");
for(ListNode *step = *head;step != NULL; step = step->link){
printf("%d ",step->data);
}
}
printf("\n");
}
void AddList(ListNode** head){
ListNode* temp = (ListNode*)malloc(sizeof(ListNode));
int num;
printf("Data register) ");
scanf("%d",&num);
temp->data = num;
temp->link = NULL;
top++;
if(*head == NULL){
*head = temp;
}
else{
ListNode *step = *head;
for(;step->link != NULL; step = step->link){}
step->link = temp;
}
DisplayList(head);
}
Your error is in how you traverse the list:
for(; (*head)->link != NULL; *head = (*head)->link) {}
At the beginning, *head is the head of the list from the calling function. By assigning to it, you overwrite it continuously, until it becomes null.
Instead, you should assign to head: It holds the address of the head node in the calling function at first and the address of the link pointer of the previous node in subsequent iterations:
for(; (*head)->link != NULL; head = &(*head)->link) {}
After this loop, head holds the address of the pointer where the new node should be stored. Assign the new node to that pointer directly:
*head = temp;
This will update the head pointer of the calling function when the list was empty and the link member of the previous node otherwise. You don't have to treat the case where the list is empty specially.
The insertion function might now look like this:
void AddList(ListNode** head, int num)
{
ListNode* temp = malloc(sizeof(ListNode));
temp->data = num;
temp->link = NULL;
while (*head) head = &(*head)->link);
*head = temp;
}
(In my opinion, reading the input and printing the list shoudl not be part of te insertion function.)
Regarding your printing function: Seeing a function like that:
void DisplayList(ListNode** head)
raises a red flag: Passing a pointer to node pointer signals that you want to modify the list (and you inadvertently do that), but printing the list only inspects it. Change the signature to
void DisplayList(const ListNode* head)
then use head instead of (*head) in the function. (Rule of thumb: If you never use *head = ... somewhere in the list, you don't need a pointer to node pointer.)

Adding node to singly linked list not working properly

I have a singly linked list struct and a local Node declared in main with my addToList() function, but every time addToList() executes it runs the case (head == NULL). Even when I already added values to the list. I am sure there is a small bug in my code, I just can't find it.
typedef struct node{
char* name;
int groupSize;
int status;
struct node* next;
}Node;
void addToList(char* name, Node* head, int groupSize, int status){
if(head == NULL){
head =(Node*)malloc(sizeof(Node));
head->name = (char*) malloc(sizeof(char)*30);
strcpy(head->name, name);
head->groupSize = groupSize;
head->status = status;
head->next = NULL;
printf("Name is %s\n\n", head->name);
}
else {
printf("entered else\n");
Node *tmp = head;
if(tmp->next!=NULL){
tmp = tmp->next;
}
tmp->next = (Node*) malloc(sizeof(Node));
tmp->next->name = (char*) malloc(sizeof(char)*30);
strcpy(tmp->next->name, name);
tmp->next->groupSize = groupSize;
tmp->next->status = status;
tmp->next->next = NULL;
}
}
int main(){
Node* head = NULL;
//TESTNG SECTION
addToList("Julio", head, 5, 7);
addToList("Francisco", head, 5, 7);
addToList("Jorge", head, 5, 7);
}
The cause of your problem is the call by value of every C function call.
At the first call of addToList(), head of the main() points to NULL.
Inside the addToList() you change the parameter head to point to a newly allocated memory region. Unfortunately, by the time addToList() returns the scope of the parameter head does not exist any more. So the head variable at the main, has exactly the same value prior the addToList() call.
The solution to this problem would be the use of double pointer for the head, or return and assign at every call the head of the list. So because previous answer covered the one solution, I will provide the other.
Node* addToList(char* name, Node* head, int groupSize, int status){
if(head == NULL){
head =(Node*)malloc(sizeof(Node));
head->name = (char*) malloc(sizeof(char)*30);
strcpy(head->name, name);
head->groupSize = groupSize;
head->status = status;
head->next = NULL;
printf("Name is %s\n\n", head->name);
}
else {
printf("entered else\n");
Node *tmp = head;
if(tmp->next!=NULL){
tmp = tmp->next;
}
tmp->next = (Node*) malloc(sizeof(Node));
tmp->next->name = (char*) malloc(sizeof(char)*30);
strcpy(tmp->next->name, name);
tmp->next->groupSize = groupSize;
tmp->next->status = status;
tmp->next->next = NULL;
}
return head;
}
int main(){
Node* head = NULL;
//TESTNG SECTION
head = addToList("Julio", head, 5, 7);
head = addToList("Francisco", head, 5, 7);
head = addToList("Jorge", head, 5, 7);
}
The head parameter will be initialized inside the function, you have to pass a pointer to a Node pointer :
void addToList(char* name, Node** head, int groupSize, int status);
Then :
*head =(Node*)malloc(sizeof(Node));
Explanations by Manos.
There are a few small problems that I see with your code.
First, I would use different names when passing in the head pointer. It might be confusing the compiler on where to look. Also, when you pass in a node pointer in addToList, you need to dereference it, so instead pass in Node**, and initialize a pointer within the method.
Second, in your addToList method, you have the following condition:
if(tmp->next!=NULL){
tmp = tmp->next;
}
this will only work when you have 2 elements in your list. Instead, make it a while loop, like so:
while(tmp->next!=NULL){
tmp = tmp->next;
}
This will correctly place the tmp pointer at the end of your list.
Hopefully this will fix some bugs,

Malloc with scope and global variables

#include<stdio.h>
#include<stdlib.h>
struct node {
int num;
struct node *next;
}*head=NULL, *curr=NULL;
void print(){
curr = head;
while(curr != NULL){
printf("%d\n", curr->num);
curr = curr->next;
}
}
struct node* memAlo(){
return (struct node *)malloc(sizeof(struct node));
}
void addNode(int no){
curr = head;
while(curr != NULL){
curr = curr->next;
}
curr = memAlo();
if(curr == NULL){
printf("\nmemory up\n");
return;
}
else{
curr->num = no;
curr->next = NULL;
printf("%d\n",curr->num);
}
}
void hellop(){
printf("%d", head->num);
}
int main(){
int i;
curr = head;
for(i=1;i<10;i++){
addNode(i);
}
print();
/*head = memAlo();
head->num = 1;
head->next = NULL;
hellop();*/
}
I am sure I have messed up somewhere. The thing is that the head pointer doesn't get the memory allocated by the memAlo() fn() but how to get there? Please help
What I am trying is to create a singly linked list holding numbers from 1 to 9 and to print them using print(). Actually AddNode() is to create single node at the end of the linked list each time the for loop in main() executes.
You set head = NULL at the point where you first defined head. Except in that one place, we never see head on the left-hand side of = anywhere in your program. So of course head is always equal to NULL and never anything else.
You will probably want to insert some code at the start of your addNode function to test whether head == NULL at that point; and if that is true, you will want to assign the result of memAlo() to head instead of curr. You will have to adjust some of the other logic as well.
Your code for allocating a node is wrong. It should create a node, make some space for it, then return it.
struct node *memAlo() {
struct node *nd = malloc(sizeof(*nd));
return nd;
}
This creates a pointer to a node, properly allocates it, then returns it.
Problems I see:
Not dealing with empty list, i.e. when head == NULL.
Creating nodes that are not linked to each other.
curr = memAlo();
allocated memory for a node and returns it to you, but it does not connect the node with anything else.
Try this:
void addNode(int no){
struct node* temp = NULL;
// Deal with an empty list.
if ( head == NULL )
{
head = memAlo();
head->num = no;
head->next = NULL;
}
// Move curr until we reach the last node of the list.
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
temp = memAlo();
if(temp == NULL){
printf("\nmemory up\n");
return;
}
else{
// Link the new node to the previous last node.
temp->num = no;
temp->next = NULL;
printf("%d\n",temp->num);
curr->next = temp;
}
}
It seems that since head is initially NULL, and then you start allocating nodes without saving the address of the first one, you lose the address of the first one, and then can't walk the list from the beginning.
The part you commented out illustrate the problem.
As a side note, there is no free in your program. Remember to always free the memory you alloc
#include<stdio.h>
#include<stdlib.h>
struct node
{
int num;
struct node *next;
};
struct node *head, *curr;
struct node *pos;
void addNode(int n)
{
if(head==NULL)
{
head = (struct node*)malloc(sizeof(struct node));
head->num = n;
head->next = NULL;
curr = head;
}
else
{
while(curr != NULL)
{
pos = curr;
curr = curr->next;
}
curr = (struct node*)malloc(sizeof(struct node));
curr->num = n;
curr->next = NULL;
pos->next = curr;
}
}
void printList()
{
curr = head;
while(curr != NULL)
{
printf("%d",curr->num);
curr = curr->next;
}
}
int main()
{
head = NULL;
curr = head;
int i, a[] = {4,5,1,2,3,9,0};
for(i=0;i<7;i++)
{
addNode(a[i]);
}
curr = head;
printList();
}
This seems to have solved my problem. I figured it out though. Thanks for all your help.

No program output in C [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
#include<stdio.h>
#include<malloc.h>
typedef struct node_t {
int i;
struct node_t* link;
} node;
node* head = NULL;
int main() {
int i = 10;
node* temp = NULL;
head = (node *)malloc(sizeof(node));
temp = (node *)malloc(sizeof(node));
if(temp == NULL) {
printf("\n malloc for temp node failed! \n");
}
else {
/* linked list logic to add the elements in the beginning */
while(i<=10) {
temp->i = i;
temp->link = NULL;
if(head == NULL) {
head = temp;
}
else {
temp->link = head;
head = temp;
}
i++;
}
}
for(temp = head; temp->link != NULL; temp = temp->link) {
printf("\n The data is:%d \n",temp->i);
}
free(temp);
free(head);
return 0;
}
I'm trying a simple linked list program. I'm not getting the output.
1) You have to allocate node (tmp) each time you are assigning value to tmp. and not allocate only one time the tmp. See the following fixed code to see how to do it
2) the following for loop is wrong:
for(temp = head; temp->link != NULL; temp = temp->link) {
This for loop is fixed in the following code
3) for the free you have to browse the whole linked list and then free each node. see the following fixed code.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct node_t{
int i;
struct node_t* link;
}node;
node* head = NULL;
int main(){
int i = 1;
node* temp = NULL;
/* linked list logic to add the elements in the beginning */
while(i<=10){
temp = (node *)malloc(sizeof(node));
if(temp == NULL){
printf("\n malloc for temp node failed! \n");
exit(1);
}
temp->i = i;
temp->link = NULL;
if(head == NULL){
head = temp;
}
else{
temp->link = head;
head = temp;
}
i++;
}
for(temp = head; temp != NULL; temp = temp->link){
printf("\n The data is:%d \n",temp->i);
}
while (head!=NULL)
{
temp = head->link;
free(head);
head = temp;
}
}
You seem to have an infinite loop! (the value of i is not changed)
You are not changing the value of variable i in the while loop as a result you never come out of the while loop.
You need something like:
int i=1;
while(i<=10){
// insert i in loop
i++;
}
You are not changing the value of loop variable i.e. i.
Also you need to do malloc inside while loop to create separate nodes. Right now, your code is modifying the same node again and again.
In addition to the node about the infinite loop, since you never modify the value of i there's something else that's wrong.
22 /* linked list logic to add the elements in the beginning */
23 while(i<=10){
24 temp->i = i;
25 temp->link = NULL;
26 if(head == NULL){
27 head = temp;
28 }
29 else{
30 temp->link = head;
31 head = temp;
Look at what you are doing in this loop. If head is NULL (it's very unlikely to be, since you allocated it back in line 15, although it's possible that the allocation could fail) you set 'head' to temp.
If head is not NULL, you set temp's 'link' to head. Then you set head to temp. Then you loop and do it all over again.
So you end up with head pointing to temp, and temp->link pointing to temp... a circular list of exactly one node.
Try this instead:
int main()
{
int i = 0;
node *temp;
/* linked list logic to add the elements in the beginning */
while(i != 10)
{
/* First, allocate a new node */
temp = (node *)malloc(sizeof(node));
if(temp == NULL)
return -1; /* yikes */
/* now set its value */
temp->i = i++;
/* and link it into the list, at the beginning */
temp->link = head;
head = temp;
}
/* Now traverse the list, starting from 'head' */
temp = head;
while(temp != NULL)
{
/* save the current node in a temporary variable */
node *temp2 = temp;
/* and move 'temp' to point to the next node in the list */
temp = temp->link;
/* print the current node */
printf("\n The data is: %d\n", temp2->i);
/* and free the memory */
free(temp2);
}
return 0;
}

Resources