#include <stdlib.h>
#include <stdio.h>
#include "sorted_tree.h"
int insert_value(int value, struct TreeNode *n) {
if (value < n->value) {
if (n->left_child == NULL) {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = value;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
n->left_child = tpointer;
printf("links eingefügt\n");
}
else {
insert_value(value, n->left_child);
}
return 0;
}
else if (value > n->value) {
if (n->right_child == NULL) {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = value;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
n->right_child = tpointer;
printf("rechts eingefügt\n");
}
else {
insert_value(value, n->right_child);
}
return 0;
}
else {
return 1;
}
}
void print_inorder(struct TreeNode *n) {
if (n == NULL) {
printf("r");
return;
}
else {
print_inorder(n->left_child);
printf("%d ", n->value);
print_inorder(n->right_child);
}
}
int main() {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = 5;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
insert_value(6, tpointer);
printf("%d", tpointer->right_child->value);
printf("%d", tpointer->right_child->value);
}
The first printf() in the main outputs "6" which is correct, but the second one outputs a hug random nummer as if the address has been changed. The 6 should be inserted into the right child node so I expected 66 as the output. Why those this happen and how can I fix it?
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
tpointer->value=value;
Those blocks of code inside the if/else if of insert_value are not correct. This is because struct TreeNode t={0}; creates an automatic variable with lifetime only within the enclosing scope. In this case, the lifetime is only within the if/else if block. Keeping a reference to the variable and using it beyond that will result in Undefined Behaviour.
The solution is to create variables that have lifetimes beyond the function. The most common way to do that is to use dynamically allocated memory:
struct TreeNode *tpointer = malloc(sizeof(*tpointer));
Don't forget to free all dynamically allocated memory when it is no longer needed.
The approach when a first node of a tree is not allocated dynamically as in your program
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
tpointer->value=5;
tpointer->left_child=NULL;
tpointer->right_child=NULL;
is not good. In fact you can not create or use an empty tree.
All nodes in a tree should be allocated dynamically when it is required.
So the pointer n within the function insert_value in general can be equal to NULL for an empty tree. You need to check it. Otherwise statements like this
if(value<n->value){
can invoke undefined behavior.
Also within the function you are setting a pointer to a local object of the type struct TreeNode as for example
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
After exiting the function the local object t will not be alive. So an invalid pointer will be added to the tree.
You need to allocate a new node dynamically.
Also the function in fact returns an arbitrary number 0 or 1 because the function does not return the final value of subsequent recursive calls of the function.
Also it would be logically more consistent to return 1 in case when a new node is added and 0 otherwise.
I would declare and define the function the following way
int insert_value( struct TreeNode **n, int value )
{
if ( *n == NULL )
{
*n = malloc( sizeof( struct TreeNode ) );
( *n )->value = value;
( *n )->left_child = NULL;
( *n )->right_child = NULL;
return 1;
}
else if ( value < ( *n )->value )
{
return insert_value( &( *n )->left_child, value );
}
else if ( ( *n )->value < value )
{
return insert_value( &( *n )->right_child, value );
}
else
{
return 0;
}
}
And if in main you have a pointer to the root node declared like
struct TreeNode *root = NULL;
then the function is called like
insert_value( &root, value );
Related
I'm currently learning C and also some datastructures such as binary search trees etc. I have trouble understanding HOW exactly changing pointer values within a function works in some cases and in others doesn't... I'll attach some of my code I wrote. It's an insert function which inserts values in the correct places in the BST (it works as it should). I tried working with pointers to pointers to be able to change values withing a function. Even though it works, im still really confused why it actually does.
I don't quite understand why my insert function actually changes the BST even though I only work with local variables (tmp, parent_ptr) in my insert function and I don't really dereference any pointers apart from " tmp = *p2r " in the insert function.
Thanks for helping out.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
struct TreeNode** createTree(){
struct TreeNode** p2r;
p2r = malloc(sizeof(struct TreeNode*));
*p2r = NULL;
return p2r;
}
void insert(struct TreeNode** p2r, int val){
// create TreeNode which we will insert
struct TreeNode* new_node = malloc(sizeof(struct TreeNode));
new_node -> val = val;
new_node -> left = NULL;
new_node -> right = NULL;
//define onestep delayed pointer
struct TreeNode* parent_ptr = NULL;
struct TreeNode* tmp = NULL;
tmp = *p2r;
// find right place to insert node
while (tmp != NULL){
parent_ptr = tmp;
if (tmp -> val < val) tmp = tmp->right;
else tmp = tmp->left;
}
if (parent_ptr == NULL){
*p2r = new_node;
}
else if (parent_ptr->val < val){ //then insert on the right
parent_ptr -> right = new_node;
}else{
parent_ptr -> left = new_node;
}
}
int main(){
struct TreeNode **p2r = createTree();
insert(p2r, 4);
insert(p2r, 2);
insert(p2r, 3);
return 0;
}
Let's analyze the approach step by step.
At first we consider the following simple program.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode *head, int val )
{
head = malloc( sizeof( struct TreeNode ) );
head->val = val;
head->left = NULL;
head->right = NULL;
}
int main(void)
{
struct TreeNode *head = NULL;
printf( "Before calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
create( head, 10 );
printf( "After calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
return 0;
}
The program output is
Before calling the function create head == NULL is true
After calling the function create head == NULL is true
As you can see the pointer head in main was not changed. The reason is that the function deals with a copy of the value of the original pointer head. So changing the copy does not influence on the original pointer.
If you rename the function parameter to head_parm (to distinguish the original pointer named head and the function parameter) then you can imagine the function definition and its call the following way
create( head, 10 );
//...
void create( /*struct TreeNode *head_parm, int val */ )
{
struct TreNode *head_parm = head;
int val = 10;
head_parm = malloc( sizeof( struct TreeNode ) );
//...
That is within the function there is created a local variable head_parm that is initialized by the value of the argument head and this function local variable head_parm is changed within the function.
It means that function arguments are passed by value.
To change the original pointer head declared in main you need to pass it by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it. Thus dereferencing the pointer in a function you will get a direct access to the original object.
So let's rewrite the above program the following way.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode **head, int val )
{
*head = malloc( sizeof( struct TreeNode ) );
( *head )->val = val;
( *head )->left = NULL;
( *head )->right = NULL;
}
int main(void)
{
struct TreeNode *head = NULL;
printf( "Before calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
create( &head, 10 );
printf( "After calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
return 0;
}
Now the program output is
Before calling the function create head == NULL is true
After calling the function create head == NULL is false
In your program in the question you did not declare the pointer to the head node like in the program above
struct TreeNode *head = NULL;
You allocated this pointer dynamically. In fact what you are doing in your program is the following
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode **head, int val )
{
*head = malloc( sizeof( struct TreeNode ) );
( *head )->val = val;
( *head )->left = NULL;
( *head )->right = NULL;
}
int main(void)
{
struct TreeNode **p2r = malloc( sizeof( struct TreeNode * ) );
*p2r = NULL;
printf( "Before calling the function create *p2r == NULL is %s\n",
*p2r == NULL ? "true" : "false" );
create( p2r, 10 );
printf( "After calling the function create *p2r == NULL is %s\n",
*p2r == NULL ? "true" : "false" );
return 0;
}
The program output is
Before calling the function create *p2r == NULL is true
After calling the function create *p2r == NULL is false
That is compared with the previous program when you used the expression &head of the type struct TreeNode ** to call the function create you are now introduced an intermediate variable p2r which stores the value of the expression &head due to this code snippet
struct TreeNode **p2r = malloc( sizeof( struct TreeNode * ) );
*p2r = NULL;
That is early you called the function create like
create( &head, 10 );
Now in fact you are calling the function like
struct TreeNode **p2r = &head; // where head was allocated dynamically
create( p2r, 10 );
The same takes place in your program. That is within the function insert dereferencing the pointer p2r you have a direct access to the pointer to the head node
if (parent_ptr == NULL){
*p2r = new_node;
^^^^
}
As a result the function changes the pointer to the head node passed by reference through the pointer p2r.
The data members left and right of other nodes are also changed through references to them using the pointer parent_ptr
else if (parent_ptr->val < val){ //then insert on the right
parent_ptr -> right = new_node;
^^^^^^^^^^^^^^^^^^^
}else{
parent_ptr -> left = new_node;
^^^^^^^^^^^^^^^^^^
}
While the pointers themselves are indeed local variables, they point to a specific location in memory. When you dereference the pointer by using the -> symbol, you're basically accessing the memory where that exact variable to which the pointer is pointing to is stored. This is why your changes are reflected outside the function as well.
You basically told a local variable where your tree is stored, it helped with the insertion, and then it went out of scope. The tree itself is not a local variable so the changes are reflected on it.
I suggest reading up on how pointers work.
First of all, always remember one thing about the pointers, they store a memory address, rather than a value. For example:
int val = 5;
int copy = val;
int *original = &val;
printf("%d\n", val);
printf("%d\n", copy);
printf("%d\n", *original);
val = 8;
printf("%d\n", val);
printf("%d\n", copy);
printf("%d\n", *original);
On executing this piece of code, the output will be
5
5
5
8
5
8
Notice, how on changing the value of val, the value of copy remains the same, and the value pointed the by original changes. This happens because the pointer original points to the memory location val.
Now, coming to the insert function, although you are only working with local variables(tmp, parent_ptr), but remember they are pointer variables, they refer to a memory address. So whenever within the loop, you traverse to tmp -> right or tmp -> left, you are actually jumping in memory from one location to another, in the correct order, that's why it works. The following example will make it more clear.
56 (A)
/ \
/ \
45 (B) 60 (C)
Consider the above BST, with the memory address in brackets. Let's insert 40 into this BST. Initially, tmp will point to A, address of 56. Now 40 is less than 56, so tmp goes to left and now points to B, address of 45. Once, again it goes to left and now it is null. But by now, parent_ptr points to B. So the new node for 40 gets attached to left of B.
56 (A)
/ \
/ \
45 (B) 60 (C)
/
/
40 (D)
Hi I'm new to C and pointers and are having issues trying to implement the below doubly linked list structure. Memory leaks happened in listInsertEnd I believe? I am very confused as to why one work (at least no mem leak in output) and the other one doesn't. I have pasted only parts of the program, any help or explanation is much appreciated.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *Node;
struct node {
int value;
Node next;
Node prev;
};
typedef struct list *List;
struct list {
Node first;
Node last;
int count;
};
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
First of all, talking about memory leaks: there is no direct memory leak in your code. If the leak happens somewhere, it's outside of these functions. It's most probably because you create one or more nodes and then forget to free() them, but this has nothing to do with the two functions you show.
I see that you are using typedef to declare simple pointer types, take a look at this question and answer to understand why that's bad practice and should be avoided: Is it a good idea to typedef pointers?. Also, this particular piece of Linux kernel documentation which explains the issue in more detail.
Secondly, the real problem in the code you show is that you are using pointers after you tested that they are invalid (NULL).
Here:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
// ^^^^^^^^ BAD!
And also here:
if (newList== NULL) {
newList->first = newList->last = n;
// ^^^^^^^^^^^^^^ BAD!
If something is NULL, you cannot dereference it. Change your functions to safely abort after they detect an invalid pointer.
This can be done in multiple ways. Here's an example of correct code:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) {
fprintf(stderr, "couldn't create new node\n");
return NULL;
}
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n;
if (newList == NULL) {
return;
// You probably want to return some error value here.
// In that case change the function signature accordingly.
}
n = newNode(value);
if (newList->count == 0) {
newList->first = newList->last = n;
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
newList->count++;
}
NOTE: the check newList->count == 0 assumes that you correctly increment/decrement the count when adding/removing elements.
This typedef declaration
typedef struct node *Node;
is confusing and presents a bad style. Consider for example this statement
Node n = malloc(sizeof(*n));
somebody can think that here is a typo and should be written
Node *n = malloc(sizeof(*n));
The function
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
has undefined behavior. If newList is equal to NULL then you are trying to use memory pointed to by a null pointer.
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
And initially data members newList->first and newList->last can be equal to NULL. That also can be reason of undefined behavior because the function does not take this into account.
Before changing the function listInsertEnd you should define the function newNode the following way
Node newNode(int value)
{
Node n = malloc(sizeof(*n));
if ( n != NULL )
{
n->value = value;
n->next = NULL;
n->prev = NULL;
}
return n;
}
The function shall not issue any message. It is the caller of the function that decides whether to issue a message if it is required.
In this case the function listInsertEnd can be written the following way
int listInsertEnd(List newList, int value)
{
Node n = newNode(value);
int success = n != NULL;
if ( success )
{
n->prev = newList->last;
if ( newList->first == NULL )
{
newList->first = newList->last = n;
}
else
{
newList->last = newList->last->next = n;
}
++newList->count;
}
return success;
}
Within the main you should create the list the following way
int main( void )
{
struct list list1 = { .first = NULL, .last = NULL, .count = 0 };
// or
// struct list list1 = { NULL, NULL, 0 };
and call the function like
listInsertEnd) &list1, some_integer_value );
I have done insert a node and delete a tree with a tutorial. I test it and it works fine. However I can't understand why I need to pass by reference the root in insert, but in deleteAll just the pointer. Because I think that passing just the pointer its a value reference and then every change is only seen in the function.
typedef struct node{
int element;
struct node *left;
struct node *right;
}*tTree;
void insert(tTree *myTree, int element){
if(*myTree == NULL){
myTree= (tTree)malloc(sizeof(*myTree));
myTree->element = element;
myTree->left = NULL;
myTree->right = NULL;
}
else{
int treeElement = (*myTree)->element;
if( treeElement > element){
insert(&(*myTree)->left, element);
}
else{
insert(&(*myTree)->right, element);
}
}
}
void deleteAll(tTree myTree){
if(myTree != NULL){
deleteAll(myTree->right);
deleteAll(myTree->left);
free(myTree);
}
}
int size(tTree myTree){
if (myTree != NULL){
return 1 + size(myTree->right) + size(myTree->left);
}
else
return 0;
}
int main(){
tTree root = NULL;
insert(&root,3);
insert(&root,2);
insert(&root,4);
insert(&root,1);
printf("Number of nodes: %d\n",size(root));
deleteAll(root);
root = NULL;
printf("Number of nodes: %d\n",size(root));
return 1;
}
The deletion needs only the pointer for the statements it executes. It is not passing any information back to the calling function. However, your insertion function allocates if needed, and in that case must pass back the allocated pointer to the caller.
I cannot figure out how to run this correctly, gives segmentation error. A piece of code is below. Can you look at head too , i am not sure if it is right way of initialising head to null in another file , it is run as follows :
Table tb ;
tb= initialise_table (table_size);
tb = insert(text_words,tb);
//these 3 typedef declarations are in a "some.h" file
typedef struct node * tree_ptr;
typedef char* Key_Type;
typedef struct table* Table;
struct node {
Key_Type element;
tree_ptr left;
tree_ptr right;
};
struct table {
tree_ptr head;
};
Table init_table() {
Table head = NULL;
}
Table insert(Key_Type key ,Table temp ) {
tree_ptr t = (tree_ptr)malloc(sizeof(tree_ptr));
t->element = key;
// t->left = t->right = NULL;
if (temp->head==NULL) {
temp = (Table)malloc (sizeof (Table));
temp->head = t;
printf("empty tree ");
}
else {
temp = insert(t->element,temp);
printf("inserted into ");
}
return temp;
printf("wowo!");
}
The primary issue is in the code which, you say, is used to invoke the functions:
Table tb;
tb = insert(text_words, tb);
You have an uninitialized pointer, tb, which you pass to the function. Inside the function, you have:
Table insert(Key_Type key, Table temp)
{
tree_ptr t = (tree_ptr)malloc(sizeof(*t)); // Fixed size
t->element = key;
// t->left = t->right = NULL;
if (temp->head==NULL)
{
You're therefore accessing (dereferencing) the undefined pointer, and your program is crashing.
You should, I assume, be initializing your table with table_init(), but that function is actually no help whatsoever. It defines and initializes a local variable, but doesn't return anything even though it promises to do so.
Please see Is it a good idea to typedef pointers? The short answer is 'No, it usually isn't a good idea'.
You still have problems even if you fix the calling code like this (a necessary but not sufficient step):
Table tb = NULL;
tb = insert(text_words, tb);
or maybe:
Table tb = init_table();
tb = insert(text_words, tb);
but you need a seriously upgraded version of init_table(), such as:
Table init_table(void)
{
Table root = malloc(sizeof(*head));
root->head = NULL;
return root;
}
Your code in insert() needs to ensure that it does not dereference a null pointer (instead of an indeterminate pointer).
Table insert(Key_Type key, Table root)
{
tree_ptr t = (tree_ptr)malloc(sizeof(*t)); // Fixed size
t->element = key;
t->left = t->right = NULL;
if (root == NULL)
{
root = init_table();
root->head = t;
}
else
{
…
}
return root;
}
Given the Key_Type is a char * in disguise, you may need to review how you save the keys in the tree structure; you may need to use strdup() to copy the data. It is impossible to say for sure without seeing how you are managing the strings that you pass to the insert() function. It could be OK to just save the pointer if the calling code ensures that a new pointer is passed each time. OTOH, if the same pointer is passed each time, you definitely need to copy the data, and using strdup() is a sensible way of doing that. Note that strdup() is standard on POSIX; it is not part of standard C.
Here's one major problem:
tree_ptr t = (tree_ptr) malloc(sizeof(tree_ptr));
should be:
tree_ptr t = (tree_ptr) malloc(sizeof(struct node));
Your code doesn't actually do any binary search. Indeed, it just infinitely recurses creating new nodes. Try something more like this:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Node
{
char *element;
struct Node *left;
struct Node *right;
} Node;
typedef struct
{
Node *root;
size_t size;
} Tree;
void Tree_init(Tree *t);
Node *Tree_insert(Tree *t, const char *key);
void Tree_insert_r(Node *subtree, Node *n, size_t size);
void Tree_pre_order_r(Node *subtree);
void Tree_init(Tree *t)
{
t->root = NULL;
t->size = 0;
}
Node *Tree_insert(Tree *t, const char *key)
{
Node *ret = (Node*) malloc(sizeof(Node));
if (ret)
{
ret->left = ret->right = NULL;
if ((ret->element = strdup(key))) /* make a copy of key */
{
if (NULL != t->root)
Tree_insert_r(t->root, ret, t->size);
else
t->root = ret;
++t->size;
}
else
{
free(ret);
ret = NULL;
}
}
return ret;
}
void Tree_insert_r(Node *subtree, Node *n, size_t size)
{
int cmp = strcmp(n->element, subtree->element);
if (cmp < 0 || (cmp == 0 && size % 2 == 0))
{
if (NULL != subtree->left)
subtree = subtree->left;
else
{
subtree->left = n;
return;
}
}
else
{
if (NULL != subtree->right)
subtree = subtree->right;
else
{
subtree->right = n;
return;
}
}
Tree_insert_r(subtree, n, size);
}
void Tree_pre_order_r(Node *subtree)
{
if (NULL == subtree)
return;
fprintf(stdout, "'%s'\n", subtree->element);
Tree_pre_order_r(subtree->left);
Tree_pre_order_r(subtree->right);
}
int main()
{
Tree t;
Tree_init(&t);
Tree_insert(&t, "Hello");
Tree_insert(&t, "World!");
Tree_insert(&t, "etc.");
Tree_pre_order(t.root);
return 0;
}
I wrote to following code which does not work. The application crashes on the print method.
Any idea where it goes wrong?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int item;
struct LinkedList *Next;
} LinkedList;
int main()
{
LinkedList vaz;
vaz.item = 14123;
vaz.Next = 0;
add(&vaz,123);
add(&vaz,9223);
Print(&vaz);
return 0;
}
void Print(LinkedList* Val)
{
if(Val != 0){
printf("%i\n",(*Val).item);
Print((*Val).Next);
}
}
void add(LinkedList *Head, int value)
{
if((*Head).Next == 0 )
{
LinkedList sab;
sab.item = value;
sab.Next = 0;
(*Head).Next = &sab;
}
else{
add((*Head).Next,value);
}
}
Your add method should allocate memory dynamically, you are using automatic allocation (local variables), which is freed when you 'leave' the function. This will cause an undefined behavior when you try to access this memory later on.
void add(LinkedList *Head, int value)
{
if((*Head).Next == 0 )
{
LinkedList sab; <-- need to be allocated dynamically
sab.item = value;
sab.Next = 0;
(*Head).Next = &sab;
}
else{
add((*Head).Next,value);
}
}
You did not allocate heap memory to the Linked list you create. I think you should allocate memory on the heap when you add elements to the linked list. The linked list variable 'sab' is local to the method and so the memory get deallocated as soon as the function goes out of scope.
To add an element, you need to do as follows:
LinkedList *sab = (struct LinkedList*) malloc (sizeof(struct LinkedList));
if( sab != NULL )
{
sab->item = value;
sab->next = NULL;
}
For more details, you can refer: http://www.cprogramming.com/snippets/source-code/singly-linked-list-insert-remove-add-count
add should dynamically allocate memory as follows:
void add(LinkedList *Head, int value)
{
if (Head == NULL)
return;
if((*Head).Next == NULL )
{
LinkedList *sab = malloc(sizeof(LinkedList));
if ( sab == NULL ) {
// Error: ran out of memory (really shouldn't happen, but could)
return;
}
(*sab).item = value;
(*sab).Next = NULL;
(*Head).Next = sab;
}
else{
add((*Head).Next,value);
}
}
Also, the recursive call is "overkill" in this case. A simple loop would suffice:
void add(LinkedList *Head, int value)
{
if (Head == NULL)
return;
while ((*Head).Next != NULL)
Head = (*Head).Next;
LinkedList *sab = malloc(sizeof(LinkedList));
if ( sab == NULL ) {
// Error: ran out of memory (really shouldn't happen, but could)
return;
}
(*sab).item = value;
(*sab).Next = NULL;
(*Head).Next = sab;
}
I'd likewise avoid the recursive call for printing:
void Print(LinkedList* Val)
{
while (Val != NULL) {
printf("%i\n", (*Val).item);
Val = (*Val).Next;
}
}
If you have a function which removes items from the list, you need to ensure that you do a free on the pointer to that item that's removed.
Your LinkedList *Head doesn't have any memory First assign memory to it as given below-
LinkedList *Head = (struct LinkedList*)malloc(sizeof(struct LinkedList));