How to build a Linked_list_builder function in C - c

I am learning about linked list, I want to make a function which creates a linked list, after that I want to make a for loop which will print our linked list at main function.
I tried this:
#include <stdio.h>
#include <stdlib.h>
typedef struct linked_list {
int data;
struct linked_list* link;
}node;
//building list
node linked_list_builder(int length) {
node* list;
list = (node*) malloc(length * sizeof(node));
for(int i=0;i<length;i++)
{
printf("Data in list no.%d at index %d = ",i+1,i);
scanf("%d",list->data);
list->link += 1;
}
return *list;
}
int main() {
int length;
printf("Enter the length of Linked list:\n");
scanf("%d", &length);
node list = linked_list_builder(length);
//printing list
for(int i=0;i<length;i++)
{
printf("index %d->list %d = %d\n",i,i+1,list.data);
list.link++;
}
return 0
}
I don't know what's the exact problem, I don't know how can I return my linked list from function, and How can I actually travel it and print its data?

You have two problems:
As pointed out by #WhozCraig:
You are reserving space for all nodes at once, if that were possible, you would have no need to create a list (with its handicap of memory fragmentation and also needing an extra pointer to point to the next node) and in that case it would be enough to use an array.
A list is useful when you don't know the number of elements you need beforehand. If you really need a list, store the position of the first element of the list in a variable (head) and add elements to that list one by one through a push function:
node *linked_list_push(node *tail, int data) {
node *curr = calloc(1, sizeof(node));
curr->data = data;
if (tail != NULL) {
tail->link = curr;
}
return curr;
}
node *head = NULL, *tail = NULL;
// pushing list
for (int i = 0; i < length; i++) {
tail = linked_list_push(tail, i);
if (head == NULL) {
head = tail;
}
}
// printing list
while (head) {
node *temp = head;
printf("%d\n", head->data);
head = head->link;
free(temp);
}
And as pointed out by #Kuro:
scanf wants a pointer:
scanf("%d",list->data);
should be
scanf("%d",&list->data);

Related

Program to create a linked list not working

Only the head element gets printed and no element gets printed further.
My guess is that the code inside else{.....} inside the createLinkedList(int n) function portion isn't seem to be doing it's job.
Code is below :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node * next;
}*head;
void createLinkedList(int n)
{
int i;
struct Node *temp, *p;
for(i=1; i<=n; i++)
{
// First thing we do is create an ISOLATED NODE WHICH IS NOT LINKED TO ANYTHING
temp = (struct Node *)malloc(sizeof(struct Node));
printf("Now enter your element %d of linked list: ",i);
scanf("%d",&(temp->data));
temp->next = NULL;
// ISOLATED NODE CREATED. SINCE THIS IS UNLINKED, WE MUST STORE IT'S POINTER VARIABLE TO NULL
if(head == NULL) // Meaning our Linked List is empty
head = temp;
else // Meaning our Linked List is not empty. Has at least one element.
{
p = head;
while(p != NULL)
p = p->next; // Accessing Last pointer of Linked List
p = temp; // THAT IOSOLATED NODE Is Hereby Connected to our final Linked LIST Element
}
printf("\n");
}
}
int main()
{
head = NULL;
printf("Enter the length of your linked list: ");
int n;
scanf("%d", &n);
printf("\n");
createLinkedList(n);
return 0;
}
Change while(p != NULL) p = p->next;
to
while(p->next != NULL)
p = p->next;
That would give you the last pointer position where you can insert your node. Right now, p will be null at the end of the iteration.
After that you need to do p->next = temp so that your newly created node is added to the linked list.
Instead of looping in else block, we can track the tail pointer for last node in linked list. Below is modified code:
void createLinkedList(int n)
{
int i;
struct Node *temp, *tail;
for(i=1; i<=n; i++)
{
// First thing we do is create an ISOLATED NODE WHICH IS NOT LINKED TO ANYTHING
temp = (struct Node *)malloc(sizeof(struct Node));
printf("Now enter your element %d of linked list: ",i);
scanf("%d",&(temp->data));
temp->next = NULL;
// ISOLATED NODE CREATED. SINCE THIS IS UNLINKED, WE MUST STORE IT'S POINTER VARIABLE TO NULL
if(head == NULL) // Meaning our Linked List is empty
{
head = temp;
tail = temp;
}
else // Meaning our Linked List is not empty. Has at least one element.
{
tail->next = temp; // THAT IOSOLATED NODE Is Hereby Connected to our final Linked LIST Element
tail = temp;
}
printf("\n");
}
}
int main()
{
head = NULL;
printf("Enter the length of your linked list: ");
int n;
scanf("%d", &n);
printf("\n");
createLinkedList(n);
return 0;
}
your code working but you lose the addresses of the next nodes when you are using while(p != NULL) so you should change it to while(p->next != NULL){p=p->next;}{p->next=temp;}.

How to change the data of a node in Linked list in C?

struct:
//linked list
struct list
{
int32_t data;
struct list *next;
};
struct list *head;
at first, initialize linked list (every node be 0):
void initLinkedList(int size)
{
head = (struct list*)malloc(sizeof(struct list)*size);
struct list *current = head;
for(int i = 0; i < size; i++)
{
(current+i)->data= 0;
}
}
function:
void changeNode(int32_t element, int index)
{
struct list *current = head;
for (int i = 0; i < index; i++)
{
current = current->next;
}
current->data= element;
}
so basically, I want to create a linked list with size nodes, then change the data of the node through function.
But I'm getting Segmentation fault at this line in function:
current->localVar = element;
So, how can I change the data of a node without inserting a new one?
You must consider whether you have requested to change an index that doesn't exist in your list, but otherwise you are close. You are not iterating your initLinkedList in a traditional manner (you are treating the list like an array) As a side-note: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?.
Let's start with your initLinkedList function. You have declared head globally (assuming) and then go to fill your list with zeros. In doing so, you never initialize any of your ->next pointers. You don't end up with a linked-list -- you have a block of allocated nodes.
You should iterate current = current->next; and set each ->next pointer, not just use the offset +i. You are able to initialize your data like that due to allocating all nodes in a continual block -- but any node added later will not be contiguous in memory and none of your ->next pointers are initialized.
Now on to your changeNode function. You must fix your initLinkedList to initialize the ->next pointers. Then you need to change the return type from void to struct list* so you can return a pointer to the changed node on success or NULL on failure. Currently, you have no way of knowing if your change succeeded or failed.
Making the changes you could do:
struct list *changeNode (int32_t element, int index)
{
struct list *current = head;
for (int i = 0; i < index; i++) {
if (!current->next) {
fputs ("error: request exceeds no. of nodes in list.\n", stderr);
return NULL;
}
current = current->next;
}
current->data = element;
return current;
}
Look things over and let me know if you have further questions.
So, here void initLinkedList(int size) you aren't creating/initializing a linked list instead you are declaring an array of type struct list dynamically with size no. of elements and then you are initializing all of them with value 0.
To initialize your linked list code this:
void initLinkedList(int size)
{
if((head = (struct list*)malloc(sizeof(struct list)*size)) == NULL)
{
printf("Memory Unavailable.\n");
exit(1);
}
struct list *current = head;
for(int i = 0; i < size; i++)
{
current->data = 0;
if ((current->next = (struct list*)malloc(sizeof(struct list))) == NULL)
{
printf("Memory Unavailable.\n");
exit(2);
}
current = current->next;
}
current->next = NULL;
}
Then to changeNode, code this:
void changeNode(int element, int index)
{
struct list *current = head;
int count = 0;
while(count != index)
{
if(current->next)
current = current->next;
count++;
}
current->data = element;
}
Here I'm adding another function to print the linked list:
void print(struct list *head)
{
if(head->next)
{
printf("%d", head->data);
head = head->next;
print(head);
}
}
main():
int main(void)
{
initLinkedList(5);
changeNode(5, 4);
print(head);
delete(head);
printf("Memory freed.\n");
return 0;
}
Now you can see the Sample Output:
00005
Memory freed.
One more thing, if you are confused about this:
if ((current->next = (struct list*)malloc(sizeof(struct list))) == NULL)
I can help you. In the above line of code, we're allocating memory to current->next and checking if memory is allocated successfully or not.
Freeing the memory allocated to linked list using delete() function:
void delete( struct list *head )
{
struct list *current = head;
struct list *next = NULL;
while(current != NULL)
{
next = current->next;
free(current);
current = next;
}
}

How to return lists in c functions?

As the title says I need to write a function which fill a list with int typed by the user, and later on print them, but i'm having troubles with the insert function, which does not actually put the values typed in the list. Here's the code:
the typedefs:
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
and the functions:
list lins(list l)
{
int i;
list root = NULL;
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
l = (list)malloc(sizeof(item));
l->value = i;
l->next = root;
root = l;
} while (i != 0);
return l;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
Sorry if my code is poorly written but I'm having a hard time understanding the concept of lists.
Edit: added functions calls
main()
{
lins(l);
showlist(l);
}
Edit 2: here's the output of the code:
output
Edit 3: Here's the sample of code my professor give us to work with lists:
http://www.mediafire.com/file/wj152pw1ojkxf1j/10a_-Liste-_2018.pdf
Your insertion function inserts in reverse order. That is because you assign root to l->next and l to root. Also the number 0 is included in the list when the user tries to end the insertion process.
In main(), you don't seem to assign the return value of the function lins() to a variable, and if you passed l declared as List l = NULL; to the function lins(), then a copy of it will be used, and so, the original variable won't be altered. What you really need is something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
list lins(void)
{
list node = NULL;
list root = NULL;
list tail = NULL;
printf("inserire dati ('0' per terminare):\n");
int i;
scanf("%d", &i);
while(i != 0)
{
node = (list)malloc(sizeof(item));
node->value = i;
node->next = NULL;
if (!root)
root = node;
else
tail->next = node;
tail = node;
scanf("%d", &i);
}
return root;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
int main(void)
{
list head = lins();
showlist(head);
system("pause");
return 0;
}
Of course, I should point out that you should free the list once you are done with it.
First of, I see no point in passing item *l as an argument to lins function.
The root or better, head of the list should not be changed once you assign something to it, unless you want to delete the list.
void lins(item **head){
item *new_node = malloc(sizeof(item));
int i;
if(!new_node){
printf("Memory allocation failed!\n");
exit(1);
}
scanf("%d", &i);
new_node->value = i;
new_node->next = NULL;
node *temp = *head;
if(!temp)
*head = new_node;
else{
while (temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
return ;
}
After you write lins like this, showlist can look as follow:
void showlist(item *head){
printf("List is: \n");
do{
printf("%d", head->value);
head=head->next;
}while(head!=NULL);
}
As for the main function you need to declare the head first.
int main(){
item *head = NULL;
lins(&head);
showlist(head);
return 0;
}
more detailed explanation to follow...
So from what I understand, you want to prepend to your linked-list. I will try to use your typedefs, though many comments have given better options to use, you could change the implementation later.
Realise that lins(list l) is never utilising the value of the parameter l passed to it. That is overriden by the malloc. It is prepending elements to the list, and finally returns the new head of your list. That new head has to be passed to showlist() for printing. What you might be doing is initialising one element of the list in main, and passing that to lins and showlist. lins doesnt bother with the parameter and returns a completely new list, but when you pass that old list to showlist it is interpreted as an empty list.
So you can simply change usage of lins to be used as a creator of linked-lists.
So declaring list lins() {...} and using it in main() like this should work:
int main() {
list l;
l = lins();
showlist(l);
return 0;
}
struct list_element {
int value;
struct list_element *next;};
typedef struct list_element * list;
void lins(list *l){
list tmp = NULL;
list last = *l;
int i;
if (last){
while(last->next){ // go to last child of list
last = last->next;
}
}else{
last = (list)malloc(sizeof(struct list_element));
}
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
last->value = i;
last->next = (list)malloc(sizeof(struct list_element));
last = last->next;
} while (i != 0);}
void show(list li){
list tmp = li;
if(li){
while(tmp){
printf("%d at %p\n",tmp->value, tmp);
tmp = tmp->next;
}
}}
int main(){
list a = (list)malloc(sizeof(struct list_element));
lins(&a);
show(a);
return 0;}

how to print out a singly linked list in reverse order?

struct node
{
int info;
struct node *next;
};
typedef struct node node;
void *printRev(node *head){
int count=0;
int i;
node *beforeFin;
node *tempHead;
tempHead = head;
while(tempHead->next != NULL){
count++;
tempHead->next = tempHead->next->next; //LAST ITERATION SHOULD BE AT THE END OF LIST
}
printf("COUNT IS: %d\n", count);
for(i = 0; i <= count; i++){
beforeFin = Prev(head, tempHead->next);
printf("%d", beforeFin->info);
}
printf("\n");
}
As of now this prints out:
COUNT IS: 3
Segmentation fault (core dumped)
Prev returns a pointer to the node before the given pointer (tempHead->next) my intention was for this to print out the singly linked list in reverse order using the for loop above. So the ->info of the given node should return 5 in the example below (after the first iteration).
Before the printf that prints the count, tempHead->next should point to the final node.
Right now I am passing in 2 3 5 4 and this is giving me the count before the 4. Id like for this to print out 4 5 3 2
I would appreciate any help given, I am a beginner as you might be able to tell. Thank you all in advance!
I could do this using recursion but I'd like to learn figure out this method.
To print a single linked list in reverse order you can use a recursive function. You have to step into the recursion to the end and print the elements of the list right before you leave the recursion function:
void printReverse(node *act)
{
if ( act == NULL ) // terminate if end of list is reached
return;
printRev( act->next ); // print next node
printf( "%d ", act->info ); // print this node
}
If you do not want to use recursion, you can of course reverse the list, then print the list and finally reverse it again.
Reversing a list is not difficult. Traverse through the list, take each element and reorder it in front of the head of the list.
node * reverse(node *head)
{
node *act, *prev;
if ( head == NULL )
return;
prev = head;
act = head->next;
while ( act != NULL )
{
prev->next = act->next;
act->next = head;
head = act;
act = prev->next;
}
return head;
}
void printReverse(node *head)
{
node *act;
act = reverse(head);
while ( act != NULL )
{
printf( "%d ", act->info ); // print this node
act = act->next;
}
reverse(head);
}
As you want to avoid recursion, you need to reverse the list first. I see some attempt in the original code but it doesn't look correct. Try the following:
node *current = head;
if (current != NULL) {
node *prev = NULL;
for (node *next = current->next; ; next = (current = next)->next) {
current->next = prev;
prev = current;
if (next == NULL)
break;
}
}
Then current will point to the head of the list and you can traverse using the next link over the list. Note that it will modify your original list but this is expected as I understood the original requirement.
The issue with the recursive algorithm is that, if you're a bit paranoid like me, the list could be large enough to cause the recursive calls to sum up and overflow the stack. If the list is from some user input then this could be used for a denial of service attack. Thus I see two reasonable choices:
Create a reversed copy of the list and print that.
Reverse the list in place, print it, possibly reverse it back.
The later is interesting if you're working in a memory constrained setting or with large lists.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
struct node {
int value;
struct node * next;
};
void reverse_inplace (struct node ** list) {
assert(list != NULL);
struct node * follow = NULL, * lead = *list;
while (lead != NULL) {
struct node * next = lead->next;
lead->next = follow;
follow = lead;
lead = next;
}
*list = follow;
}
void print (struct node const * head) {
printf("( ");
while (head) {
printf("%d ", head->value);
head = head->next;
}
printf(")");
}
void link (struct node * array, size_t count) {
struct node * follow = NULL;
while (count-->0) {
array[count].next = follow;
follow = &(array[count]);
}
}
void fill (struct node * list, int value, int const step) {
while (list != NULL) {
list->value = value;
value += step;
list = list->next;
}
}
int main () {
size_t const sizes[] = {1, 2, 6};
size_t const num =
sizeof(sizes) / sizeof(sizes[0]);
size_t caseId = 0;
for (; caseId < num; ++caseId) {
struct node * head =
malloc(sizeof(*head) * sizes[caseId]);
printf("Case %zu: List of size %zu\n",
caseId, sizes[caseId]);
link(head, sizes[caseId]);
fill(head, caseId, caseId);
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print (head);
printf(" \n");
reverse_inplace(& head);
free(head);
}
printf("Case %zu: empty list \n", caseId);
struct node * head = NULL;
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print(head);
printf(" \n");
return 0;
}
(Live on ideone)

Linked List removeNode C Programming

I was having some confusion between ListNode and LinkedList. Basically my question was divided into 2 parts. For first part, I was supposed to do with ListNode. The function prototype as such:
int removeNode(ListNode **ptrHead, int index);
All function were working fine for the ListNode part. Then as for the second part, I was supposed to change the function above to this:
int removeNode(LinkedList *11, int index);
My code for part 1 which is working fine look like this:
int removeNode(ListNode **ptrHead, int index) {
ListNode *pre, *cur;
if (index == -1)
return 1;
else if (findNode(*ptrHead, index) != NULL) {
pre = findNode(*ptrHead, index - 1);
cur = pre->next;
pre->next = cur->next;
return 0;
}
else
return 1;
}
ListNode *findNode(ListNode *head, int index) {
ListNode *cur = head;
if (head == NULL || index < 0)
return NULL;
while (index > 0) {
cur = cur->next;
if (cur == NULL) return NULL;
index--;
}
return cur;
}
And here is my entire code for the part 2 which is not working:
#include "stdafx.h"
#include <stdlib.h>
typedef struct _listnode {
int num;
struct _listnode *next;
}ListNode;
typedef struct _linkedlist {
ListNode *head;
int size;
}LinkedList;
void printNode2(ListNode *head);
int removeNode2(LinkedList *ll, int index);
int main()
{
int value, index;
ListNode *head = NULL, *newNode = NULL;
LinkedList *ptr_ll = NULL;
printf("Enter value, -1 to quit: ");
scanf("%d", &value);
while (value != -1) {
if (head == NULL) {
head = malloc(sizeof(ListNode));
newNode = head;
}
else {
newNode->next = malloc(sizeof(ListNode));
newNode = newNode->next;
}
newNode->num = value;
newNode->next = NULL;
scanf("%d", &value);
}
printNode2(head);
printf("\nEnter index to remove: ");
scanf("%d", &index);
removeNode2(ptr_ll, index);
printNode2(head);
return 0;
}
void printNode2(ListNode *head) {
printf("Current list: ");
while (head != NULL) {
printf("%d ", head->num);
head = head->next;
}
}
int removeNode2(LinkedList *ll, int index) {
ListNode *head = ll->head;
if (head == index)
{
if (head->next == NULL)
{
printf("There is only one node. The list can't be made empty ");
return 1;
}
/* Copy the data of next node to head */
head->num = head->next->num;
// store address of next node
index = head->next;
// Remove the link of next node
head->next = head->next->next;
return 0;
}
// When not first node, follow the normal deletion process
// find the previous node
ListNode *prev = head;
while (prev->next != NULL && prev->next != index)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
printf("\n Given node is not present in Linked List");
return 1;
}
// Remove node from Linked List
prev->next = prev->next->next;
return 0;
}
When I try to run the part 2, the cmd just not responding and after a while, it just closed by itself and I have no idea which part went wrong. I was thinking am I in the correct track or the entire LinkedList part just wrong?
When I tried to run in debug mode, this error message popped up:
Exception thrown at 0x01201FD1 in tut.exe: 0xC0000005: Access violation reading location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
Thanks in advance.
You say that you got the linked list to work wihen the list is defined via the head pointer only. In this set-up, you have to pass a pointer to the head pointer when the list may be updated, and just the head pointer when you only inspect the list without modifying, for example:
int removeNode(ListNode **ptrHead, int index);
ListNode *findNode(ListNode *head, int index);
Here, the head pointer is the handle for the list that is visible to the client code.
The approach with the list struct defines a new interface for the linked list. While the head node is enough, it might be desirable to keep track of the tail as well for easy appending or of the number of nodes. This data can be bundles in the linked list struct.
What that means is that the handling of the nodes is left to the list and the client code uses only the linked list struct, for example:
typedef struct ListNode ListNode;
typedef struct LinkedList LinkedList;
struct ListNode {
int num;
ListNode *next;
};
struct LinkedList {
ListNode *head;
ListNode *tail;
int size;
};
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
void ll_append(LinkedList *ll, int num);
void ll_remove_head(LinkedList *ll);
int main()
{
LinkedList ll = {NULL};
ll_append(&ll, 2);
ll_append(&ll, 5);
ll_append(&ll, 8);
ll_print(&ll);
ll_prepend(&ll, 1);
ll_prepend(&ll, 0);
ll_print(&ll);
ll_remove_head(&ll);
ll_print(&ll);
while (ll.head) ll_remove_head(&ll);
return 0;
}
There's also one difference: In the head-node set-up, the head node might be null. Here, the list cannot be null, it must exist. (Its head and tail members can be null, though.) Here the list is allocated on the stack, its address &ll must be passed to the functions.
In the linked list set-up, the distinction between modifying and read-only access is done via the const keyword:
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
In your example, you take a mixed approach with two independent structures, a head node and a list. That can't work, one single list is described by one struct, pick one.
The advantage to the linked list structure approach is that all required data like head, tail and size are always passed together to a function. You can also hide the implementation from the user by not disclosing the struct members, so that theb user can only work on pointers to that struct.
Finally, here's an example implementation of the above interface for you to play with:
void ll_print(const LinkedList *ll)
{
ListNode *node = ll->head;
while (node != NULL) {
printf("%d ", node->num);
node = node->next;
}
putchar('\n');
}
void ll_prepend(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = ll->head;
nnew->num = num;
ll->head = nnew;
if (ll->tail == NULL) ll->tail = ll->head;
ll->size++;
}
void ll_append(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = NULL;
nnew->num = num;
if (ll->tail == NULL) {
ll->tail = ll->head = nnew;
} else {
ll->tail->next = nnew;
ll->tail = nnew;
}
ll->size++;
}
void ll_remove_head(LinkedList *ll)
{
if (ll->head) {
ListNode *ndel = ll->head;
ll->head = ll->head->next;
ll->size--;
free(ndel);
}
}

Resources