Recursive linked list in C - c

I've just tried to implement a recursive linked list append in C, and for some reason l keeps being NULL no matter what I do, even though I malloc when encountering a NULL value.
The following code prints nothing. Any ideas?
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
unsigned v;
struct node* next;
} node;
void insert(unsigned x, node* l) {
if (l == NULL){
node* new_node = (node*)malloc(sizeof(node));
new_node->v = x;
new_node->next = NULL;
l = new_node;
}
else {
insert(x, l->next);
}
}
void print(node *l) {
if (l == NULL) return;
printf("%d\n", l->v);
print(l->next);
}
int main(){
node* l = NULL;
insert(1, l);
insert(2, l);
print(l);
return 0;
}
Help much appreciated.
EDIT: Even if I initialize it, it's still the same.

#include <stdlib.h>
#include <stdio.h>
typedef struct node {
unsigned v;
struct node* next;
} node;
node* insert(unsigned x, node** ll) {
if (*ll == NULL){
*ll = (node*)malloc(sizeof(node));
(*ll)->v = x;
(*ll)->next = NULL;
}
else {
insert(x, &(*ll)->next);
}
}
void print(node *l) {if (l == NULL) return;
printf("%d\n", l->v);
print(l->next);
}
int main(){
node* l = NULL;
insert(1, &l);
insert(2, &l);
print(l);
return 0;
}
compiled with no gcc no switches
output:
1
2

First off, you're passing l to your function by value so you won't see any changes made to it. Currently, when you set l to new_node, you only change the local value of l in the method insert. You may want to modify your function to return l and set l in your main to the return value of this function.
node *insert(int x, node *l){
//.... your method
return l;
}
In main:
node *l = NULL;
l = insert(1, l);
l = insert(2, l);
Second, your recursive call will not append nodes to your LL for the same reason. Change that call to this:
l->next = insert(x, l);

Related

C - How to print a string element in a pointer to struct?

I'm relearning linked list data structure and I stumbled upon this problem.
#include <stdlib.h>
#include <stdio.h>
struct Node{
char url[50];
struct Node *next;
};
typedef struct Node Node;
void add_url(Node * h, Node * c, Node * n){
Node * temp;
temp = malloc(sizeof(Node));
printf("\nType or paste your URL: ");
scanf("%s", temp->url);
if(h == NULL){
h = temp;
h->next = NULL;
c = h;
}else{
c->next = temp;
c = c->next;
n = c->next;
}
}
int main(){
Node * h = NULL; // head
Node * c; // current
Node * n; // next
add_url(h, c, n);
printf("%s", h->url);
return 0;
}
Why is the output NULL? How exactly do you get a string input from a pointer to struct?
Here is a possible solution. I have added some checks to avoid segmentation fault (access violation), buffer overflow in scanf, initialized variables and the function now returns the new head (Could instead return current node).
#include <stdlib.h>
#include <stdio.h>
struct Node {
char url[50];
struct Node* next;
};
typedef struct Node Node;
Node *add_url(Node** h, Node** c, Node** n) {
Node* temp;
if ((h == NULL) || (c == NULL) || (n == NULL))
return NULL;
if ((temp = malloc(sizeof(Node))) == NULL)
return NULL;
printf("\nType or paste your URL: ");
if (scanf("%50s", temp->url) != 1)
return NULL;
if (*h == NULL) {
temp->next = NULL;
*h = temp;
*c = *h;
}
else {
(*c)->next = temp;
*c = temp;
*n = temp;
}
return *h;
}
int main() {
Node* h = NULL; // head
Node* c = NULL; // current
Node* n = NULL; // next
if (add_url(&h, &c, &n) == NULL) {
perror("add_url failed: ");
return 1;
}
printf("%s", h->url);
return 0;
}

Print reversely the elements of a list using recursion

I want to print reversely the elements of a list using recursion, but I get an execution error !
Can someone help?
typedef struct node
{
int val;
struct node* next;
}node;
typedef struct list
{
node* head;
}list;
void display(list L)
{
if(L.head == NULL) return;
L.head= L.head->next;
display(L);
printf("%d\t",L.head->val);
}
void display(node *N){
if(N != NULL){
display(N->next);
printf("%d\t",N->val);
}
}
and in main:
int main (void)
{
//...
display (L.head);
Instead of using :
typedef struct list
{
node* head;
}list;
you can simply pass the "node n" instead, and call it recursively using n->next, as follows:
void display(node *n){
if(n != NULL){
display(n->next);
printf("%d\t",n->val);
}
}
And then call that method from the outside as follows:
display(node->head);
or
display(node.head);
Depending on how you have allocated the structure "node".
Side Note:
I would actually renamed your structures to:
typedef struct List
{
int val;
struct List* next;
}List;
and then call:
void display(List *l){
if(l != NULL){
display(l->next);
printf("%d\t",l->val);
}
}
IMO it better expresses the use-case in hand.
A Full example:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct List
{
int val;
struct List* next;
}List;
void display(List *l){
if(l != NULL){
display(l->next);
printf("%d\t",l->val);
}
}
List *addElement(List *l, int val){
if(l == NULL){
List *node = malloc(sizeof(List));
node->val = val;
node->next = NULL;
return node;
}
else
l->next = addElement(l->next, val);
return l;
}
void freeList(List *l){
if(l != NULL){
freeList(l->next);
free(l);
}
}
int main(){
List *l = NULL;
l = addElement(l, 1);
l = addElement(l, 2);
l = addElement(l, 3);
l = addElement(l, 4);
l = addElement(l, 5);
display(l);
freeList(l);
}
OUTPUT:
5 4 3 2 1

Segmentation Fault with C List when not using global List

I have written some code creating a singly linked list and then converting it to a dynamic array in C.
The code works just fine if I only create a global variable for the list header. If I want to create the list in my main function, however, I always get a segmentation fault.
The code below works just fine as soon as I create a global list variable instead and remove the list as parameter from all functions.
Can anyone tell me why this won't work if I want to pass the list as a parameter to the function and thus be able to create multiple lists?
#include <stdlib.h>
#include <stdio.h>
typedef struct NodeStruct* Node;
typedef struct NodeStruct {
Node next;
int val;
} NodeStruct;
typedef Node List;
Node newNode(int x){
Node n = (Node)malloc(sizeof(NodeStruct));
if(n!=NULL){
n->val = x;
n->next = NULL;
return n;
}
else{
printf("ERROR: Could not allocate memory!\n");
}
exit(1);
}
void prepend(List l, Node node){
if (l == NULL) l = node;
else{
node->next = l;
l = node;
}
}
void printList(List l){
if(l!=NULL){
Node n = l;
while(n->next != NULL){
printf("%d, ", n->val);
n = n->next;
}
printf("%d\n", n->val);
}
else{
printf("ERROR: List empty!\n");
}
}
/*=============================*/
int* arrOf(List l){
if(l==NULL){
printf("ERROR: List empty\n");
exit(1);
}
int size = 0;
Node n = l;
while(n!=NULL){
size++;
n = n->next;
}
int* arr = (int*)malloc((size+1)*sizeof(int));
n = l;
int i = 0;
arr[i++] = size;
while(n != NULL){
arr[i++] = n->val;
n = n->next;
}
printf("Returning Array\n");
return arr;
}
int main(int argc, char *argv[]){
List l;
prepend(l, newNode(5));
prepend(l, newNode(6));
prepend(l, newNode(7));
prepend(l, newNode(8));
prepend(l, newNode(9));
prepend(l, newNode(4));
printList(l);
printf("\n===========================================\n");
int* arr = arrOf(l);
for(int i = 0; i < 10; ++i){
printf("%d, ", arr[i]);
}
return 0;
}
When you initialize List l in main, you are not assigning a default value. It is stored on the stack and not initialized. This means the value is undefined and not necessarily null.
When you are creating List l globally, the variable is stored in the bss segment and initialized with null.
Change your declaration of List l to:
List l = NULL;
This function
void prepend(List l, Node node){
if (l == NULL) l = node;
else{
node->next = l;
l = node;
}
}
deals with a copy of the value of the pointer l declared in main
List l;
that moreover was not initialized.
So changing of the copy in these statements within the function
if (l == NULL) l = node;
//...
l = node;
does not influence on the original value of the pointer declared in main.
You have to write at least like
void prepend(List *l, Node node){
node->next = *l;
*l = node;
}
and in main
List l = NULL;
The function can be called like
prepend( &l, newNode(5) );
That is the pointer to the head node must be passed to the function by reference.
Also you need to free all the dynamically allocated memory for the list and the array.

basic questions about Linkedlist and Node Insertion

I have some problems about my sub-major lecture.
First of all, sorry for poor English.
anyway, Professor told me that It was very east to solve, just change some lines and it would be work.
but I can't finish this code ontime.
when I play? debug? my code, couldn't print 'List'.
How to print properly about my LinkedList code?
+ I have to fix few lines. not entire code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct ListNode {
int data;
struct ListNode* link;
}listNode;
void insertFirstListNode(listNode* num, int data) {
listNode* newNode = malloc(sizeof(listNode));
newNode->link = num->link;
newNode->data = data;
num->link = newNode;
}
typedef struct {
listNode* head;
} linkedList_h;
linkedList_h* createLinkedList_h() {
linkedList_h* Newlist = (linkedList_h*)malloc(sizeof(linkedList_h));
Newlist->head = NULL;
return Newlist;
}
void printList(linkedList_h* L) {
listNode* p;
printf("L = (");
p = L->head;
while (p != NULL) {
printf("%d", p->data);
p = p->link;
if (p != NULL) printf(", ");
}
printf(") \n");
}
void main() {
linkedList_h* m;
m = createLinkedList_h();
insertFirstListNode(m, 10);
printList(m);
}
As per my understanding you are trying to add the node to the beginning of the linked list. In that case the below fix should be working fine.
Please have error handling in all the functions like NULL inputs, Malloc fails etc ...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct ListNode {
int data;
struct ListNode* link;
}listNode;
typedef struct {
listNode* head;
} linkedList_h;
void insertFirstListNode(linkedList_h* num, int data) {
listNode* newNode = (listNode *)malloc(sizeof(listNode));
newNode->link = num->head;
newNode->data = data;
num->head = newNode;
}
linkedList_h* createLinkedList_h() {
linkedList_h* Newlist = (linkedList_h*)malloc(sizeof(linkedList_h));
Newlist->head = NULL;
return Newlist;
}
void printList(linkedList_h* L) {
listNode* p;
printf("L = (");
p = L->head;
while (p != NULL) {
printf("%d", p->data);
p = p->link;
if (p != NULL) printf(", ");
}
printf(") \n");
}
int main() {
linkedList_h* m;
m = createLinkedList_h();
insertFirstListNode(m, 10);
printList(m);
return 0;
}

Having a trouble with linked lists (adding and printing)

I'm too new on data structures, actually i began yesterday. Here is the code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int x;
node *next;
};
void addToList(node *r, int a);
void printList(node *r);
int main()
{
node *root;
root = NULL;
for (int i = 0; i < 5; i++)
{
int a;
scanf("%d", &a);
addToList(root, a);
}
printList(root);
return 0;
}
void addToList(node *r, int a)
{
while (r != NULL)
r = r -> next;
r = (node *)malloc(sizeof(node));
r -> x = a;
r -> next = NULL;
}
void printList(node *r)
{
while (r != NULL)
{
printf("%d ", r -> x);
r = r -> next;
}
printf("\n");
}
I expect the program gets new 5 elements into the list and then prints them. But end of the program nothing is happening. What is my fault?
The problem is in the addToList() function. If you want to update the root node of the list you have to define your function like that:
void addToList(node **r, int a)
Otherwise, you're sending the pointer to root and doing whatever you doing inside the function. But it doesn't affect root's value on main() and it remains NULL.
If you want to change the value of the pointer, you have to send from main() the address of the pointer to the function ==> addToList(&root, a);.
So now we can update where root points to. But it's not enough because you want root to always point to the beginning of the list ==> you want to update it only in the first call to addToList().
Last problem is to add the new created node as the last node in the list. You can do that by saving a temporary pointer to the last node. See my comments in the code (marked my changes with <<<):
void addToList(node **root, int a) <<<
{
node *r = *root; <<<
node *last = NULL; <<<
while (r != NULL) {
last = r; <<<
r = r -> next;
}
r = (node *)malloc(sizeof(node));
r -> x = a;
r -> next = NULL;
if (last == NULL) { <<<
// this is true only on the first call to
// addToList, so we update root only once
*root = r;
} else {
// all other times we add the new node to be the last one
last->next = r;
}
}
You have root = NULL but your addtoList function checks if root !=NULL. So the test fails there and nothing gets added.
You should have something like this instead:
void addToList(node *r, int a) {
struct node *temp;
temp=(struct node *)malloc(sizeof(struct node));
temp->data = a;
if (r== NULL) {
r = temp;
r->next = NULL;
}
else {
temp->next = r;
r = temp;
}
}
Here, the first mistake is that you have not taken the *root pointer variable as global, so it will not update the value of the *root whenever a new node is inserted. It will keep the value of *root as NULL.
The below code has comments in it, which will explain the various mistakes done by you very easily.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int x;
node *next;
};
node *root; //Declaring the *root as global
void addToList(int a);
void printList();
//removing the *root as parameter from both the functions
int main()
{
root = NULL;
for (int i = 0; i < 5; i++)
{
int a;
scanf("%d", &a);
addToList(a);
}
printList();
return 0;
}
void addToList(int a)
{
//Declaring a temporary pointer(*temp) to avoid the value loss of the *root pointer
node *temp=root;
//Declaring a new node to save the data taken from the user
node *nn = (node *)malloc(sizeof(node));
//Assigning the values to the new node(*nn)
nn->x=a;
nn->next=NULL;
//Checking that the root node is NULL or not
//If root is empty, then new node is assigned to *root
if(root == NULL)
{
root=nn;
}
//Else, we will first find the last node of the linklist using the *temp pointer
else
{
while (temp->next != NULL)
temp = temp -> next;
//Assigning the new node after the last node of the linklist
temp->next=nn;
}
}
void printList()
{
node *r=root;
while (r != NULL)
{
printf("%d ", r -> x);
r = r -> next;
}
printf("\n");
}

Resources