I am new to C and try to learn how to implement C on linked list. I am really confused why I can't access myList in the main function? because when I try to myList->data, it's segmentation fault. I think there's some error in my addtohead function?
Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE{
int data;
struct NODE *next;
}node;
node * myList;
node * addToHead(node*, int);
void printList();
int main(){
myList = NULL;
int input;
while (scanf("%i",&input) == 1){
addToHead(myList, input);
printf("%d \n", myList->data);
}
printf("My List:\n");
printList(myList);
return 0;
}
node* addToHead(node* head, int newData){
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
void printList(node* head){
node *temp = head;
while(temp != NULL){
printf("%d ", temp->data);
temp = temp -> next;
}
printf("\n");
}
Your addToHead function is supposed to return the mallocated memory back to caller.
So you should assign the return value to mylist at first:
int main(){
node *myList = NULL;
int input;
while (scanf("%i",&input) == 1){
myList = addToHead(myList, input);
printf("%d \n", myList->data);
}
printf("My List:\n");
printList(myList);
return 0;
}
Into your addToHead function you wrote
head = temp;
But head has local scope and the assigned value is not reflected to the pointer myList.
To do so you have to use pointer to pointer.
int main(){
node *myList = NULL;
int input;
while (scanf("%i",&input) == 1)
{
if (addToHead(&myList, input) == true)
{
printf("%d \n", myList->data);
}
else
{
fprintf(stderr, "Error addToHead\n");
}
}
return 0;
}
bool addToHead(node** head, int newData){
node *temp = malloc(sizeof(node));
if (temp != NULL)
{
temp -> data = newData;
temp -> next = NULL;
if(head != NULL)
{
temp -> next = *head;
}
*head = temp;
return true;
}
return false;
}
Finally always remember to check the malloc return value: it can fail.
You return the new head node from addToHead, but you don't do anything with it. You need to assign this value to myList to update it:
myList = addToHead(myList, input);
Also, you misspelled a variable on the following line:
printf("%d \n", myListd->data);
It should be:
printf("%d \n", myList->data);
In this function definition
node* addToHead(node* head, int newData){
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
The parameter node* head is a local variable of the function. Any changes of the parameter will not influence on the original argument. The function parameters will be destroyed after exiting the function.
You can consider the function definition and its call the following way
addToHead(myList, input);
//...
node* addToHead(/*node* head, int newData*/){
node *head = myList;
int newData = input;
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
So the original variable myList will not be changed after the function call. You have to assign explicitly the returned value to the variable
myList = addToHead(myList, input);
Also the function has a drawback. It does not report an error in case when the new node was not allocated.
A better approach to write the function looks the following way
int /* _Bool */ addToHead( node **head, int newData )
{
node *temp = ( node * )malloc( sizeof( node ) );
int /* _Bool */ success = temp != NULL;
if ( success )
{
temp -> data = newData;
temp -> next = *head;
*head = temp;
}
return success;
}
In this case the function can be called in a loop the following way
while ( scanf( "%i", &input ) == 1 && addToHead( &myList, input ) )
{
//...
}
Related
I am new to Data Structures and C. this code work correctly in creating and inserting a node but when i call destroy function its case a Segmentation Fault.It seems to work correctly if i put all the code in the main function instead of other functions.
what cases this bug is :
• destroy
• delete IF deleted the head of the Linked List Only
can anyone please explain to me what is wrong with that?
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int value;
struct node *next;
} node;
node *create_node(int value);
unsigned char insert(node *head, int value);
unsigned char delete_node(node *head, node *old_node);
node *search(node *head, int value);
unsigned char destroy(node *head);
int main(void)
{
node *head = create_node(1);
insert(head, 3);
insert(head, 2);
destroy(head);
for(node *i = head; i != NULL; i = i -> next)
{
printf("%i\n", i -> value);
}
}
// Will create a node and return it if succeeded else it will return NULL
node *create_node(int value)
{
node *new_node = malloc(sizeof(node));
// Check if the node created successfully or not
if (new_node == NULL)
{
return NULL;
}
new_node -> value = value;
new_node -> next = NULL;
return new_node;
}
// Insert the node to a list at the beginning of it, return 0 if succeed else number NOT 0
unsigned char insert(node *head, int value)
{
node *new_node = create_node(value);
// Check if the node created successfully or not
if (new_node == NULL)
{
return 1;
}
// Check if the List is exist or not
if (head == NULL)
{
return 2;
}
new_node -> next = head -> next;
head -> next = new_node;
return 0;
}
// Delete the node, return 0 if succeeded else number NOT 0
unsigned char delete_node(node *head, node *old_node)
{
// Check if the node is exist or not
if (old_node == NULL)
{
return 1;
}
node *back = head;
// If delete the first node ONLY
if (head == old_node)
{
free(old_node);
old_node = NULL;
return 0;
}
while (back -> next != old_node)
{
back = back -> next;
}
back -> next = old_node -> next;
free(old_node);
return 0;
}
// destroy the whole linked list, returns 0 if destroid successfully else number NOT 0
unsigned char destroy(node *head)
{
// Check if the List is exist or not
if (head == NULL)
{
return 1;
}
node *temp = head;
while (temp != NULL)
{
temp = temp -> next;
destroy(temp);
delete_node(head, temp);
}
delete_node(head, head);
return 0;
}
// return Pointer to node if founded it else return NULL
node *search(node *head, int value)
{
while (head != NULL)
{
// If founded it return it's pointer
if (head -> value == value)
{
return head;
}
else
{
head = head -> next;
}
}
return NULL;
}
I don't see exactly where the problem is here, but I do observe that your distroy (sic...) function is unnecessarily complicated. If your purpose is to destroy the entire list, you don't need to call a destroy_node routine. Just do something like this: (pseudocode ...)
while (head != NULL) {
temp = head->next;
free(head);
head = temp;
}
Your destroy_node routine also looks unnecessarily complicated. There are only two cases to consider: deleting the head node, and deleting a node that is not the head node. (pseudocode)
if (node == NULL) return;
if (node == head_node) {
head_node = head_node->next;
free(node);
} else {
temp = head_node;
while ((temp != NULL) {
if (temp->next == node) {
temp->next = temp->next->next; // link it out of the list
free(node);
return;
} else {
temp = temp->next;
}
}
}
your problem is here :
while (temp != NULL)
{
temp = temp -> next;
delete_node(head, temp);
}
your function delete_node(node *head, node *old_node) at the end execute:
free(old_node); // you free temp !
and you dont set old_node to NULL if your free this memory, your can't loop a second time here (because temp deleted):
while (temp != NULL)
{
temp = temp -> next;
delete_node(head, temp);
}
Below I have made a simple Linked List in C. The code is currently producing a segmentation fault which I find odd because I was copying an example from our current book. The only thing I did to the code was put the code into the method "addToList". I'm aware the segmentation fault is coming from the method addToList but I do not know where I made a mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
Any help with telling me what is wrong or where I'm making the mistake would be greatly appreciated.
Look carefully at your code:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
You are not initializing the memory, so head->val and head->next are not
initialized. Because of that
while (current->next != NULL) {
current = current->next;
}
will loop an undefined amount of times. The first current->next is most
probably not NULL, so current = current->next get executed. At that point current is pointing to nowhere, hence the undefined behaviour which in your case leads to a segfault.
You have to initialized the memory like this:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
But you could also use calloc, which also sets the memory to 0, thus you don't have to initialize the values (in this case):
Node *head = calloc(1, sizeof *head);
if(head == NULL)
// error handling
You should always check for the return value of malloc/calloc/realloc.
Also note that the signature of the main function can be one of these:
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
edit
Another error I've noticed right now:
x = scanf("%d");
That's not how scanf works. You have to pass a pointer, scanf saves the
scanned value through the passed pointer. scanf returns the number of matched
values on success, in this case, success would be 1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
Also don't use the same variable x for the loop iteration and user input,
otherwise you are messing with the loop.
edit
User user3629249 wrote in the comment
good information, however the result will be the first entry in the linked list will contain garbage.
Better to declare head via: Node *head = NULL; and the function addToList() check for NULL and proceed accordingly.
That's right, the head element doesn't save any number in this way.
Option 1: double pointer
Here addToList receives a double pointer. The initialization of head occurs
when *head points to NULL. The function allocates memory for it, initializes
the memory, saves the value and returns. In the concurrent calls of addToList
*head won't be NULL, so addToList looks for the end of the list.
I've made small changes in the way you do malloc and realloc. Also I added
an implementation of freeList which should be used to free the memory:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
Option 2: addToList returns a pointer to the head
Here addToList takes a pointer to the head. If it's NULL, it allocates
memory and initializes like in the shown above. If head is not NULL, the
functions looks for the last element and the returns the head. On error the
function returns NULL.
Node *addToList(Node *head, int val) {
if(head == NULL)
{
head = calloc(1, sizeof **head);
head->val = val;
head->next = NULL;
return head;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return NULL;
current->next->val = val;
current->next->next = NULL;
return head;
}
int main(void)
{
int x;
Node *head = NULL, *tmp;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
tmp = addToList(head, val);
if(tmp == NULL)
{
fprintf(stderr, "Not enough memory\n");
freeList(head);
return 1;
}
head = tmp;
}
printList(head);
freeList(head);
return 0;
}
When i am printing linked list , i get runtime error
#include stdio.h
#include stddef.h
typedef struct
{
int info;
struct DEMO1 *next;
} DEMO1;
void insertatlast(DEMO1 * p, int o);
void printl(DEMO1 * p);
int main()
{
int temp;
DEMO1 *head = NULL;
if (head == NULL)
while (1)
{
printf("ENTER 0 to exit");
scanf("%d", &temp);
if (temp == 0)
break;
insertatlast(head, temp);
}
printl(head);
return 0;
}
void insertatlast(DEMO1 * head, int data)
{
if (head == NULL)
{
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
head = node;
}
else
{
DEMO1 *temp;
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
temp->next = node;
}
}
void printl(DEMO1 * head)
{
DEMO1 *temp;
temp = head;
printf("%d", temp->info);
while (temp != NULL)
{
printf(":) %d\n", temp->info);
temp = temp->next;
}
}
When head is NULL, head is changed within the insertatlast() function only and not in main(). return head to update head in main() also.
DEMO1* insertatlast(DEMO1 * head, int data)
{
if (head == NULL)
{
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
head = node;
}
else
{
DEMO1 *temp;
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
temp->next = node;
}
return head;
}
int main()
{
int temp;
DEMO1 *head = NULL;
if (head == NULL)
while (1)
{
printf("ENTER 0 to exit");
scanf("%d", &temp);
if (temp == 0)
break;
head=insertatlast(head, temp);
}
printl(head);
return 0;
}
When you compile it (after fixing the missing <> in #includes, you can read some warning from your compiler — hopefully you have warnings enabled. Even if they doesn't solve your problem, it is a good habit to take a look at them.
Lines like
DEMO1 *head = NULL;
if (head == NULL)
should suggest you you are doing something wrong. The fact the if-body is executed, tell you alone that head is NULL when you call insertatlast. That's fine, you expect it. What you likely do not expect is that your head is not modified by the call to insertatlast: so when you call printl, head is NULL still, and calling
`printl(NULL);`
is problematic, because of
temp = head;
... temp->info ...
I guess someone told you that if you want to modify a value of a variable in the caller, you have to pass a pointer to that variable, and that since you have already a pointer, you get confused.
The fact is, a pointer is a variable too, and if you need to modify it, you must get the pointer to... a pointer.
DEMO1* head = NULL;
//...
insertatlast(&head, temp);
and your prototype for the insert would be
void insertatlast(DEMO1 **head, int data);
Then, you modify the caller variable (the DEMO1*), access it and so on, by using *head (don't forget that in insertatlast head has type DEMO1**, and so *head has type DEMO1*).
Note
Do not cast malloc return value; in C
DEMO1* node = malloc(sizeof (DEMO1));
suffices.
This code adds only one element to the end of list(just creates head element, nothing after that).What is wrong in my program? Should I pass two items in function, head and item or just one?
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct MyList
{
int x;
int y;
struct MyList * next;
}List;
typedef List * Item;
void AddEnd(Item * head);
void PrintList(Item * head);
int main(void)
{
int response;
Item head;
head = NULL;
while(1)
{
printf("1- Print, 2 - Add to End, 3 - exit\n");
scanf("%d", &response);
switch(response)
{
case 1: PrintList(&head); break;
case 2: AddEnd(&head); break;
case 3: return 0;
}
}
return 0;
}
void PrintList(Item * head)
{
Item temp;
temp = *head;
while(temp != NULL)
{
printf("%d %d\n", temp->x, temp->y);
temp = temp->next;
}
}
void AddEnd(Item * head)
{
Item new, temp;
new = (Item)malloc(sizeof(new));
printf("Enter x and y: ");
scanf("%d %d", &new->x, &new->y);
new->next = NULL;
if(*head == NULL)
{
*head = new;
}
else
{
temp = *head;
while(temp != NULL)
{
temp = temp->next;
}
temp = new;
}
}
This code down that I just tried don't work also:
void AddEnd(Item * head, Item * item)
{
Item new, temp;
new = (Item)malloc(sizeof(new));
printf("Enter x and y: ");
scanf("%d %d", &new->x, &new->y);
new->next = NULL;
if(*head == NULL)
{
*head = new;
}
else
{
temp = *head;
while(temp != NULL)
{
temp = temp->next;
}
temp = new;
*item = temp;
}
}
In your AddEnd function in the else clause, when you exit the while loop, temp is now NULL. However, the element before it is still pointing to NULL.
Try something like
temp = *head;
if (temp->next == NULL) {
temp->next = new;
} else {
while((temp->next) != null) {
temp = temp->next;
}
temp->next = new;
}
in your else clause.
(This, and the apparent issue with your understanding of malloc referenced by the others, new should be a Item * and the malloc call should be malloc(sizeof(Item)). You also don't need to cast the return value of malloc (indeed, there are some pitfalls that happen if you do).) Reading your typedefs a little more closely, new should actually be an Item (since it's a pointer to a List struct and you have typedef List* Item). Try new = malloc(sizeof(List)); and just declare new to be of type List *. (The typedef List * Item makes your code hard to read; it becomes less clear what's a pointer and what isn't.)
You need to change this:
new = (Item)malloc(sizeof(new));
To this:
new = (Item *)malloc(sizeof(List));
Hope this helps
We have a problem with our LinkedList in C.
When I count how many nodes should be in the list, I always get 1
LL count: 1
This is the Add, count and get last element of the list code:
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
return temp;
}
CPU_INT32U countLL(LL * head)
{
CPU_INT32U elements = 0;
LL * temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
It's called in this way:
addLL(list);
temp = countLL(list);
Debug_LOG("LL count: %i", temp);
where LL * list; is a global variable, and temp is in local scope.
I hope anyone can see where I went wrong
Greetings,
Sjaak and Gerrit
I see several issues in your code :
you should always protect your linked list operations by testing if the list pointer is valid (i.e. not null)
you cannot allocate a first item to an empty list due to the way you allocate the first new item : you change head but the modification won't be propagated outside of the function. You should pass a "pointer to a list pointer" (i.e. a LL**) that is equivalent to "the address of a LL*"; See how I call addLL() and how I have modified its prototype and the head assignment
if your list is only one block long, it won't be counted as you count only if there is a successor, see how I have modifed the order of the do / while condition
I propose the modified code that works for 1, 2 or any list length (I have just changed the CPU_INT32U to int to compile quickly with MinGW, I could have typedef'ined):
#include <stdio.h>
#define DEF_NULL 0
typedef struct tagL {
int ID;
int TCB;
struct tagL *next;
} LL;
void addLL(LL ** head);
LL * getLastNode(LL * head);
int countLL(LL * head);
void addLL(LL ** head)
{
LL *newNode;
LL *tail = getLastNode(*head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!*head)
*head = newNode;
else
tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
if (head){
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
}
return temp;
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
if (head){
do {
temp = temp->next;
elements++;
} while(temp != DEF_NULL);
}
return elements;
}
int main(int argc, char *argv[]){
LL *list = 0;
printf("LL test\n");
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
}
Output :
LL test
length = 1
length = 2
length = 3
On Windows nothing's wrong whit this function - strange ...
ideone also shows good output.
#include <stdio.h>
#include <stdlib.h>
typedef struct LL{
struct LL *next;
}LL;
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != NULL)
{
temp = temp->next;
}
return temp;
}
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != NULL)
{
newNode->next = NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
while(temp->next != NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
int main() {
LL *h = malloc(sizeof(*h));
addLL(h);
addLL(h);
addLL(h);
printf("%d\n", countLL(h)); // prints 3 as expected
}
CPU_INT32U countLL(LL * head){CPU_INT32U elements = 0;LL * temp = head;while(temp->next != DEF_NULL){temp = temp->next;elements++;}return elements;}
in this function you are declaring elements variable as auto
so its storage gets deallocated as soon as function exits , as memory now free to allocate to different variable, so may be overwritten hence previous cvalue gets lost
so to avoid this please use static in declaring variable.....
as static variables memory gets deallocated only after execution of whole program
please try....
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
There is a problem here, if (the global) head happens to be NULL, it will be dereferenced by the getLastNode() function:
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
Here temp->next != ... will cause temp to be dereferenced. That would cause NULL pointer dereferences if temp happens to be NULL. (as in the call by the insert function. You could add an extra test (or use pointers to pointers which is cleaner):
while(temp && temp->next != DEF_NULL)
Update (to show that the pointer to pointer version is cleaner)
#include <stdlib.h>
#include <stdio.h>
#define DEF_NULL NULL
#define CPU_INT32U unsigned
typedef struct link {
struct link *next;
} LL;
LL *globhead=NULL;
LL **getTailPP(LL **ppHead);
CPU_INT32U countLL(LL * ptr);
void addLL(LL **ppHead);
void addLL(LL **ppHead)
{
ppHead = getTailPP(ppHead);
*ppHead = malloc(sizeof **ppHead);
if(*ppHead != DEF_NULL)
{
// newNode->ID=-1;
// newNode->TCB=-1;
(*ppHead)->next = DEF_NULL;
}
}
LL **getTailPP(LL **ppHead)
{
for( ; *ppHead; ppHead = &(*ppHead)->next ) {;}
return ppHead;
}
CPU_INT32U countLL(LL * ptr)
{
CPU_INT32U elements = 0;
for(; ptr != DEF_NULL; ptr=ptr->next) { elements++; }
return elements;
}
int main()
{
unsigned count;
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
return 0;
}