Inserting Element single linked List C - 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);

Related

variable "tmp" used in loop condition not modified in loop body

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}

Need clear understanding why value isn't affected even if passed by reference? [duplicate]

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed last year.
I have a question on which I seek clarity with pointers. I am coming from javascript so I am having a hard time with pointers. I have written singly linked list code mostly by myself and the code is fully working. I have created a function to delete the particular item in the linked list. The function in the main is this:
insertAtMiddle(&head, 3, 500);
insertAtMiddle(&head, 100, 500);
There is one thing I can't understand. First I would like to show the code of my delete function.
void insertAtMiddle(node_t **head, int location, int newData){
node_t *temp = *head;
while(temp->next != NULL){
if (temp->data == location)
{
break;
}
//Shouldn't that also change the original head or move the head to the left as it is passed by reference
temp=temp->next;
}
if (temp->data != location)
{
printf("No location found for replacement!");
}
//Create new node
node_t *newNode = malloc(sizeof(node_t));
newNode->data = newData;
newNode->next = temp->next;
temp->next = newNode;
}
My question is shouldn't the temp=temp->next; inside the while loop should also affect or modify the original head? Head has been passed as a reference to this function. My confusion arises because *temp = *head, temp has been assigned head.
My full code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node_t;
void viewAllNodes(node_t *head){
node_t *tmp = head;
printf("\n");
while (tmp != NULL)
{
printf("%d--->", tmp->data);
tmp=tmp->next;
}
printf("\n");
}
void insertAtBegining(node_t **head, int data){
node_t *tmp = malloc(sizeof(node_t));
tmp->data = data;
tmp->next = *head;
*head = tmp;
}
void deleteNode(node_t **head,int data){
node_t *tmp = *head, *nodeToDelete = NULL;
//see two nodes in advance
while(tmp->next != NULL){
if (tmp->next->data == data)
{
nodeToDelete = tmp->next;
break;
}
tmp = tmp->next;
}
if (nodeToDelete == NULL)
{
printf("No node found to delete");
return;
}
tmp->next = nodeToDelete->next;
free(nodeToDelete);
}
void insertAtEnd(node_t **head, int data){
node_t *newNode = malloc(sizeof(node_t));
newNode->data = data;
newNode->next = NULL;
node_t *tmp = *head;
while (tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = newNode;
}
node_t *searchNode(node_t *head, int value){
node_t *tmp = head;
while (tmp->next != NULL)
{
if(tmp->data == value){
return tmp;
}
tmp=tmp->next;
}
return NULL;
}
void insertAtMiddle(node_t **head, int location, int newData){
node_t *temp = *head;
while(temp->next != NULL){
if (temp->data == location)
{
break;
}
//Shouldn't that also change the original head as it is passed by
temp=temp->next;
}
if (temp->data != location)
{
printf("No location found for replacement!");
}
//Create new node
node_t *newNode = malloc(sizeof(node_t));
newNode->data = newData;
newNode->next = temp->next;
temp->next = newNode;
}
int main(){
node_t *head = NULL;
insertAtBegining(&head, 1);
insertAtBegining(&head, 2);
insertAtBegining(&head, 3);
insertAtBegining(&head, 4);
insertAtBegining(&head, 5);
insertAtBegining(&head, 6);
insertAtEnd(&head, 8);
insertAtEnd(&head, 9);
insertAtBegining(&head, 100);
viewAllNodes(head);
deleteNode(&head, 1);
deleteNode(&head, 8);
insertAtMiddle(&head, 3, 500);
insertAtMiddle(&head, 100, 500);
viewAllNodes(head);
return 0;
}
You are basically doing this:
#include <stdio.h>
void foo(int* head) {
int temp = *head;
temp = 1234;
}
int main()
{
int bar = 0;
foo(&bar);
printf("bar = %d\n", bar);
}
You expect 1234 as output, but the actual output is 0.
temp is just a local copy, modifying temp will just modify temp and nothing else.

Linked List in C: Delete Second Node and Free Memory

For some reason, if I have a linked list that looks like 3->2->1->0, and I called deleteSecond(head), I get 3->1->0->0. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} *LinkedList;
int deleteSecond(LinkedList list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
LinkedList second = list->next;
list->next = list->next->next;
free(second);
return val;
}
int main() {
LinkedList head = NULL;
head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
LinkedList ptr = head;
for (int i = 0; i < 4; i++) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
printf("\n");
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
return 0;
}
I believe my deleteSecond function should be correct. I create a pointer to my second node, and then I make the head->next = head->next->next, and the I free the pointer to the second node. I don't know why I have two 0's at the end of the list.
You are creating an empty node head which is creating problem. Your last node should point to NULL. So initializing head = NULL is the correct one.
LinkedList head = NULL;
// head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
head = malloc(sizeof(LinkedList));
This is wrong. Correct would be
head = malloc(sizeof(*head));
Then again same way it would be
LinkedList newNode = malloc(sizeof(*newNode));
Now let's see what you did here.
head's data or link attribute is never initialized. So you get undefined behavior accessing it.
This is the code you wanted to write if you want to allocate memory to head.
...
int main(void) {
LinkedList head = NULL;
head = malloc(sizeof(*head));
if( head == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
head->next = NULL;
head->data = 2017; // dummy data.
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
...
...
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data); // prints 2017 also. But deletes the node that was in second position.
head = head->next;
}
return 0;
}
Here we have used one extra node for holding the dummy data. Yes! it's not needed. This dummy node is doing nothing significant other than providing an next link for the newNodes which is not needed if you just use head as LinkedList or struct LinkedNode* and allocates no memory to it. It suggests we can eliminate than and simply use the pointer to struct ListNode namely head.
Then the code will be simply like
LinkedList head = NULL;
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
There are couple of things you can consider
Don't hide pointers under typedef.
Do check the return value of malloc.
Do free the memory that you allocate after you are done working with it.
The code can be written this way also. It doesn't use the pointer under typedef and modularize the reusable codes.
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} ListNode;
void freeMemList(ListNode *head){
ListNode *temp;
while(head!=NULL){
temp = head;
head = head->next;
free(temp);
}
}
int deleteSecond(ListNode * list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
ListNode * second = list->next;
list->next = list->next->next;
free(second);
return val;
}
void printList(ListNode *head){
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
}
struct ListNode * addNodes(struct ListNode* head, int n){
for (size_t i = 0; i < n; i++) {
ListNode * newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
return head;
}
int main(void) {
ListNode * head = NULL;
head = addNodes(head,4);
printList(head);
printf("********\n");
int valDeleted = deleteSecond(head);
printf("%s %d\n","Value deleted ", valDeleted );
printList(head);
freeMemList(head);
return 0;
}

Faulty memory maniplation w / linked lists

The last printf call (printf("%d\n", current->val);) will not be executed. After the 1st printf functions' results appear, I am given the error "program.exe has stopped working". I would appreciate some help.
#include <stdio.h>
typedef struct node
{
int val;
struct node * next;
} node_t;
void print_list(node_t * head);
void main()
{
node_t * head = NULL;
head = malloc(sizeof(node_t));
if (head == NULL)
return 1;
head->val = 3;
head->next = malloc(sizeof(node_t));
head->next->val = 2;
head->next->next = malloc(sizeof(node_t));
head->next->next->val = 3;
head->next->next->next = malloc(sizeof(node_t));
head->next->next->next->val = 18;
print_list(head);
head->next->next->next->next = malloc(sizeof(node_t));
head->next->next->next->next->val = 5556;
head->next->next->next->next->next = NULL;
node_t * current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = malloc(sizeof(node_t));
current->next->val = 32;
current->next->next = NULL;
printf("%d", current->next->val);
system("pause");
}
void print_list(node_t * head) {
node_t * current = head;
while (current != NULL) {
printf("%d\n", current->val);
current = current->next;
}
}
This won't go well:
head->next->next->next = malloc(sizeof(node_t));
head->next->next->next->val = 18;
print_list(head);
You never initialized head->next->next->next->next to NULL. Instead, use calloc, or explicitly set the value to NULL. Even better, write a function to create a new node so you never forget to initialize. Even better still, write a function to insert a node.
What about something like this:
node_t * create_node( int val ) {
node_t *node = malloc(sizeof(*node));
if( node ) {
node->val = val;
node->next = NULL;
}
return node;
}
node_t * insert_value( node_t *list, int value ) {
node_t *new_node = create_node( value );
if( !new_node ) {
return list;
} else if( list ) {
new_node->next = list->next;
list->next = new_node;
}
return new_node;
}
Then you can:
node_t *head = insert_value( NULL, 3 );
node_t *tail = head;
tail = insert_value( tail, 2 );
tail = insert_value( tail, 3 );
tail = insert_value( tail, 18 );
print_list( head );
A common approach for lists is to use a dummy head node, which you never print out. It only contains a next pointer which is the start of your list and you ignore the value. If you did this, then you could also use that insert_value function to insert a value before the first element of the list. You also get the benefit that head always manages your entire list and you never have to worry about it changing.

Instanciate a temp static list head pointer in 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;
}

Resources