Instanciate a temp static list head pointer in C - c

void add_tail_r(list ** head, int elem)
{
list *current=*head;
list *temp = NULL;
if (current->next==NULL)
{
if (!( temp=(list *)malloc(sizeof(list )) ))
printf("Error");
temp->elem=elem;
temp->next=NULL;
current->next=temp;
return;
}
else
{
add_tail_r (current->next,elem);
}
}
I have this recursive function that have to insert an element into the list but when the function is recursively called it goes into an infinite loop.
How can I declare 'current' and 'temp' static if they are a self-declared types?
How can I fix this?
typedef
struct list{
int elem;
struct list*next;
} list;

void add_tail_r (list* head, int elem)
{
list* new = NULL;
list* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
new = (list*) malloc (sizeof (list));
new->elem = elem;
new->next = NULL;
temp->next = new;
}
I hope I did not make any mistake, I am currently without a C-compiler.
The intended function of it is to take a list element and iterate forward through its ->next pointer until we reach a NULL value, which means we've reached the end of the line. Once we are on that row we can allocate memory for a new element with void* malloc (size_t size);
Once we are on that part we can assign its ->elem value to our elem.
Edit #1 This takes away the recursion part, if that is required then discard this.

#include <stdlib.h>
#include <stdio.h>
typedef struct list{
int elem;
struct list*next;
} list;
void add_tail_r(list ** head, int elem)
{
list *temp = NULL;
if (*head == NULL)
{
if (!( temp=(list *)malloc(sizeof(list ))))
{
printf("Error ..");
return;
}
temp->elem = elem;
temp->next = NULL;
*head = temp;
}
else
{
add_tail_r (&(*head)->next,elem);
}
}
void print_list(list * head)
{
list *tmp=head;
while(tmp != NULL)
{
printf("%d\n" , tmp->elem);
tmp = tmp->next;
}
}
list * my_head = NULL;
int main()
{
add_tail_r(&my_head, 10);
add_tail_r(&my_head, 8);
add_tail_r(&my_head, 6);
add_tail_r(&my_head, 4);
add_tail_r(&my_head, 2);
print_list(my_head);
return 0;
}

Related

Inserting Element single linked List C

I try to insert an Element in an empty single Linked List and print that.
The code looks like this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
int val;
struct Node* next;
}ll;
void addElement(ll* List, int num){
ll* new = malloc(sizeof(ll));
if(new == NULL){
printf("NO MEMORY\n");
exit(0);
}
new->val = num;
new->next = NULL;
if(List == NULL){
List = new;
return;
}
ll* curr = List;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = new;
}
void printElements(ll* List){
ll* curr = List;
while(curr != NULL){
printf("%i\n", curr->val);
curr = curr->next;
}
}
*int main(){
ll* list = NULL;
addElement(list, 20);
addElement(list, 30);
addElement(list, 19);
printElements(list);
return 0;*
}
Does anybody see my mistake? Because it only works if i already have an Element in my List and nothing will be printed.
The function deals with a copy of the value of the pointer to the head node used as the function argument.
void addElement(ll* List, int num){
So this statement
List = new;
does not change the value of the original pointer. It changes the value of the copy of the original pointer.
The function can be defined the following way
int addElement( ll **List, int num )
{
ll *new_node = malloc( sizeof( ll ) );
int success = new_node != NULL;
if ( success )
{
new_node->val = num;
new_node->next = NULL;
while ( *List != NULL ) List = &( *List )->next;
*List = new_node;
}
return success;
}
And the function is called like
ll* list = NULL;
addElement( &list, 20);
addElement( &list, 30);
addElement( &list, 19);

How to structure linked list in C with pointers, keep getting error

I'm quite new to C and am still coming to grips with a lot of the syntax and idiosyncrasies. I'm not exactly sure what needs changing in order to make my code work but am open to any ideas. I understand that I need to utilize pointers in order to make this work but I am still lost on the specific implementation. I keep getting an error that my myList function is undeclared but I feel like I have declared it already. Is there something I am missing about how C works? Any help would be appreciated
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
}node;
node*linkedList ();
int main ()
{
struct linkedList* myList = (struct createList*)malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList ()
{
node* head;
node* current;
node*next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search(int value)
{
int index = 0;
node searchNode = head;
while(searchNode.next!= NULL)
{
searchNode = searchNode.next;
index++;
if (node.value = data)
{
break;
}
else {
index = -1;
}
}
return index;
}
}
I will be simplifying the explanations, so the terms that I will use might not be the correct one.
Proper and consistent indentation would always make your code easier to read and to fix. There were missing semi-colons too, you should watch out for that.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
} node;
node* linkedList();
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList()
{
node* head;
node* current;
node* next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode;
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead;
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search (int value)
{
int index = 0;
node searchNode = head;
while (searchNode.next != NULL)
{
searchNode = searchNode.next;
index++;
if(node.value = data)
{
break;
}
else
{
index = -1;
}
}
return index;
}
}
In main(), you should add the return 0; at the end of the function as it is an undefined behavior (AKA not a good thing to do). You could also change it to void main(), but it doesn't compile in clang.
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
You can't put a function within a function in C (nested functions). Put addNode(), getSize(), and search() outside the linkedList() function.
node* linkedList()
{
node* head;
node* current;
node* next;
}
addNode (int x)
{
node keephead = head;
...
}
int getSize ()
{
int counter = 0;
...
return counter;
}
int search (int value)
{
int index = 0;
...
return index;
}
linkedList() does literally nothing now and should be removed.
struct node* next;
} node;
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
...
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
void addNode (int x)
{
node keephead = head;
In main(), myList is the head of the currently empty linked-list, so it should be initialized to NULL. There's no linkedList data type, only node. Change it to:
node* myList = NULL;
You seem to be applying addNode(), getSize(), and search() to a variable, but C doesn't have that feature (C++ have it though). Add the linked-list head as an argument instead. addNode() needs the & address operator since it will be changing where the head starts.
addNode(&myList, 5);
addNode(&myList, 10);
addNode(&myList, 13);
printf("%d\n", search(myList, 10));
printf("The linked list is this big: %d\n", getSize(myList));
Update the function parameters of addNode(). In the while condition current.next = NULL and if statements, you were using an assignment operator instead of a comparison operator != or ==. You used the variables current and newnode, but never declared it anywhere in the function. There were lots of logic errors here. Change it to:
void addNode (node** head, int x)
{
node* current = *head;
node* newnode = malloc(sizeof(node));
newnode->data = x;
newnode->head = *head;
newnode->next = NULL;
if (*head == NULL)
*head = newnode;
else
{
while (current->next != NULL)
current = current->next;
//current is now the last node of linked list
current->next = newnode;
}
}
Do the same for the function parameters of getSize() and search(). Use node * instead for countNodes and searchNode. -> is the operator for accessing the members of a struct pointer. if statement should be put before it goes to the next node, as it would always skip the first node if left as it is. index should be put before the if statement so the index would update before it breaks out of the loop.
int getSize (node* head)
{
int counter = 0;
node* countNodes = head;
while (countNodes != NULL)
{
countNodes = countNodes->next;
counter++;
}
return counter;
}
int search (node* head, int value)
{
int index = 0;
node* searchNode = head;
while (searchNode != NULL)
{
index++;
if(searchNode->data == value)
break;
searchNode = searchNode->next;
}
if(searchNode->data != value)
index = -1;
return index;
}
Add the function prototypes before main().
void addNode (node** head, int x);
int getSize (node* head);
int search (node* head, int value);
int main()
{
node* myList = NULL;
Everything should work properly now.

I have a problem with a problem that uses lists

I have a problem with this code. I have tried to debug with gdb and Valgrind, But nothing works...
The goal of the code is to create a list, where every string is added only if no existing node with the same string in already part of the list.
This is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct node {
char *word;
struct node *next;
};
void print_list(struct node *head) {
while ((head) != NULL) {
printf(" %s -> ", head->word);
head = (head->next);
}
}
// insert a new node in head
void add_n(struct node **head, char *str) {
struct node *new;
new = malloc(sizeof(struct node));
if (new == NULL) {
printf("Not enough memory\n");
exit(EXIT_FAILURE);
}
new->word = str;
new->next = NULL;
if ((*head) == NULL){
(*head) = new;
}
while ((*head)->next != NULL) {
head = &(*head)->next;
}
(*head)->next = new;
}
// check if str is present in the list
int find_string(struct node **head, char *str) {
int found = 0;
while ((*head) != NULL) {
int i = strcmp(str, (*head)->word); //i=0 are the same
if (i == 0) {
found = 1;
return found;
}
head = &((*head)->next);
}
return found;
}
// insert a new string in the list only if is new
void insert(struct node **head, char *str) {
if (find_string(head, str) == 0) {
add_n(head, str);
}
}
void rem_ent(struct node **head, struct node *ent) {
while ((*head) != ent) {
head = &((*head)->next);
}
(*head) = ent->next;
free(ent);
}
void fini_list(struct node **head) {
while ((*head) != NULL) {
rem_ent(head, *head);
head = &((*head)->next);
}
}
int main() {
struct node *head = NULL;
insert(&head, "electric");
print_list(head);
insert(&head, "calcolatori");
print_list(head);
insert(&head, "prova pratica");
print_list(head);
insert(&head, "calcolatori");
print_list(head);
fini_list(&head);
//printf("lunghezza media = %f\n", avg_word_lenght(head));
return 0;
}
Maybe the error might be stupid, but I spent a lot of time debugging without success.
the function fini_list invokes undefined behavior due to the redundant statement
head=&((*head)->next);
because the function rem_ent already set the new value of the pointer head.
void rem_ent(struct node** head, struct node * ent){
while((*head) != ent){
head= &((*head)->next);
}
(*head)= ent->next;
free(ent);
}
Remove the statement
void fini_list(struct node** head){
while((*head) != NULL){
rem_ent(head, *head);
}
}
Also change the function add_n the following way
// insert a new node in head
void add_n(struct node ** head, char* str){
struct node * new;
new = malloc(sizeof(struct node));
if (new == NULL) {
printf("Not enough memory\n");
exit(EXIT_FAILURE);
}
new->word= str;
new->next = NULL;
if ((*head)==NULL){
(*head)=new;
}
else
{
while((*head)->next != NULL){
head = &(*head)->next;}
(*head)->next = new;
}
}
And next time format the code such a way that it would be readable.
In general you should allocate dynamically memory for strings that will be stored in nodes of the list.

getting segmentation error (core dumped) in linked list

I have looked at my code several times but couldn't find the problem. please tell me what I need to replace to get my code working.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert(int x)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head == NULL)
{
temp->next = head;
head = temp;
return;
}
struct node *temp1 = head;
while(temp1 != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
void display()
{
struct node *temp = head;
if (head == NULL)
{
printf("list is empty");
return;
}
else{
while(temp!=NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
}
int main()
{
head = NULL;
insert(3);
insert(5);
insert(6);
display();
}
The problem is in this code:
struct node *temp1=head;
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
... the while loop won't end until temp1 is NULL, so after the loop ends, it is guaranteed that temp1 is a NULL pointer ... and then you dereference that NULL pointer (via temp1->next), which causes a crash. Probably what you want to do instead is while(temp1->next != NULL) {...}
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
The only way out of this loop is for temp1 to be NULL. Then the next line attempts to used temp1 as a pointer. This is likely causing your issue. You need to instead check if the next is NULL and break leaving temp1 as the last in the list not it's next.
Pro tip for linked lists like this, they are a lot easier to modify with double pointers. Example code:
void append(struct node **list, int a) {
// skip to the end of the list:
while (*list != NULL) {
list = &(*list)->next;
}
*list = malloc(sizeof(struct node));
(*list)->data = a;
(*list)->next = NULL;
}
void display(struct node *list) {
while (list) {
printf("%d\n", list->data);
list = list->next;
}
}
void remove(struct node **list, int index) {
while (*list) {
if (--index == 0) {
struct node *temp = *list;
*list = temp->next;
free(temp);
break;
}
}
}
int main() {
struct list *mylist;
append(&mylist, 3);
append(&mylist, 4);
append(&mylist, 5);
display(mylist); // prints 3 4 5
remove(&mylist, 1);
display(mylist); // prints 3 5
remove(&mylist, 0);
remove(&mylist, 0);
// mylist is NULL again, all memory free'd
}
Note that this code needs no special cases for "is the list empty?", which makes it less complex than yours.

LinkedList adding Element

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;
}

Resources