recursively call in c to create link list - c

I am new in c so any help will be appreciated. I need to print 10 numbers from a linked list (it doesnt matter which numbers for now) I believe my code will print 9,8,7...0. for example. The linked list will be part of a struct (struct data) that will contain other variables (not important for now)
//linked list
struct listOfNodes {
struct node *root;
};
//list of parameters to send to the function to print nodes
struct data {
struct listOfNodes *list;
int total;
};
I need to send the struct (struct data) as a parameter of a recursive function (addNode). In this recursive function, I need to add a new node to the linked list and call recursively 10 times to create more nodes for the link list, then I need to print the linked list. I have the following code so far
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//node
struct node {
int value;
struct node *next;
};
//linked list
struct listOfNodes {
struct node *root;
};
//list of parameters to send to the function to print nodes
struct data {
struct listOfNodes *list;
int total;
};
void printNode(struct listOfNodes *list) {
struct node *n = list->root;
while(n!=NULL){
printf("%d\n",n->value);
n=n->next;
}
}
void addNode(void* d){ //parameter needs to be a void*
struct data *o = (struct data *)d ;
if(o->total<10) {
//create new node
struct node *n = malloc(sizeof(struct node));
n->value = o->total;
n->next = NULL;
o->total = o->total + 1;
if(o->list->root == NULL)
{
o->list->root = n;
}
else {
n->next = o->list->root->next;
o->list->root->next = n;
}
addNode(d);
}
}
int main() {
struct data *d= malloc(sizeof(struct data *));
d->total=0;
d->list=NULL;
addNode(d); //add recursively 10 times
if(d->list!=NULL) printNode(d->list);
return 0;
}
But I am getting Segmentation fault (core dumped). Can you please help me?

In your main program, you added list as NULL. But in your addNode, you only check if list->root is NULL. What's happening is when
if(o->list->root == NULL)
{
o->list->root = n;
}
is accessing list->root when list is NULL. You de reference a NULL pointer and segfault.
You probably need
struct listOfNodes *variable=malloc(sizeof(struct listOfNodes));
d->list=variable;

Changes are describe in comments
#include <stdio.h>
// #include <string.h> // <------- 4 not needed.
#include <stdlib.h>
struct node {//node
int value;
struct node *next;
};
struct listOfNodes {//linked list
struct node *root;
};
struct data {//list of parameters to send to the function to print nodes
struct listOfNodes *list;
int total;
};
void printNode(struct listOfNodes *list) {
struct node *n = list->root;
while(n!=NULL){
printf("%d\n",n->value);
n=n->next;
}
}
void addNode(struct data * d){ // <------- 3 no need to be void * so o replaced by d
if(d->total<10) {
//create new node
struct node *n = malloc(sizeof(struct node));
n->value = d->total;
n->next = NULL;
d->total = d->total + 1;
if(d->list->root == NULL)
{
d->list->root = n;
}
else {
n->next = d->list->root->next;
d->list->root->next = n;
}
addNode(d);
}
}
int main() {
struct data *d= malloc(sizeof(struct data)); // <---- 1 allocate data size not pointer size.
d->total=0;
d->list = malloc(sizeof(struct listOfNodes)); // <---- 2 alocate list !
d->list->root = NULL; // <---- 2 init root.
addNode(d); //add recursively 10 times
if(d->list!=NULL) printNode(d->list);
return 0;
}

Related

Does array initialize memory in c? [duplicate]

This question already has answers here:
initial value of int array in C
(10 answers)
Closed 2 years ago.
Having this linked list:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
typedef struct node node_t;
void printlist(const node_t*);
node_t *create_node(int);
int main(void){
int values[3] = {1,2,3};
node_t *nodes[3];
for(int i =0; i<3 ; i++)
{
nodes[i] = create_node(values[i]);
if(i!=2)
nodes[i]->next = nodes[i+1]; //HERE, can I assign next (un)initialized node?
}
node_t *header = nodes[0];
printlist(header);
}
void printlist(const node_t* header){
for(const node_t *i = header; i; i=i->next)
printf("value is %i\n",i->value);
}
node_t *create_node(int value){
node_t *new = malloc(sizeof(node_t));
new->value=value;
new->next = 0;
return new;
}
Which gives:
value is 1
value is 29590344
Command terminated
As I can see from output, the first node (header), does not have assign next struct member, which should happened from the loop. But I am assigning the next (pointer to new node) to an (un)initialized member from array (of pointer to nodes). I expect a initilization of array should also initilize a memory, when it has size. But does it? If so, then I do not understand why the assignment does not work, otherwise I understand and have to implement other loop. Thanks for answers.
Your code does not create the dynamic list as you have an array of 3 nodes. next is not needed.
You probably want something like this.
/* you need to check if memory allocation was successful */
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
int value;
struct node *next;
} node_t;
void printlist(const node_t*);
node_t *append_node(node_t *, int);
int main()
{
node_t *head = NULL, *parent = head;
for(int x = 0; x < 10; x++)
if(!head)
{
head = append_node(NULL, x);
parent = head;
}
else
{
parent = append_node(parent, x);
}
printlist(head);
}
void printlist(const node_t* head){
while(head)
{
printf("value is %i\n",head->value);
head = head -> next;
}
}
node_t *append_node(node_t *parent, int value){
node_t *new = malloc(sizeof(*new));
new->value=value;
new->next = NULL;
if(parent) parent -> next = new;
return new;
}

How to change sinlgy linked list to doubly linked list?

I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.

How to split a linked-list into two lists

I'm writing a code to split a circular linked-list to two linked lists with equal number of codes, following is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node *ptr;
struct node {
int element;
ptr prev;
ptr next;
};
typedef ptr list;
typedef ptr position;
int main() {
list L=malloc(sizeof(struct node));
list first=malloc(sizeof(struct node));
list second=malloc(sizeof(struct node));
splitlist(L,first,second);
return 0;
}
void splitlist(list L, list first,list second) {
position p,temp;
p=malloc(sizeof(struct node));
temp=malloc(sizeof(struct node));
p=L;
int count=0;
while ((p)->next != L) {
count++;
}
int c=count;
while (c!=(count/2)-1) {
p=(p)->next;
temp=(p)->next;
}
first=L;
(p)->next=NULL;
second=temp;
c=count;
while (c!=(count/2)-1) {
temp=(temp)->next;
}
(temp)->next=NULL;
}
When compiling my code it gives no errors but I'm not sure if it's working properly.
In order to get more readable and maintainable code, the first step to improve the code could be to create functions which help manipulating lists. Candidate functions are:
ListInitialize()
ListPushFront()
ListPushBack()
ListPopFront()
ListPopBack()
ListGetFirstNode()
ListGetNextNode()
ListGetFront()
ListGetBack()
ListEmpty()
...
With a proper set of arguments and return values of course.
Then you can write your splitlist function using those basic list operation functions and your code will be easier to read and to reason about.
Also, in order to handle an empty list, you should have an extra list type which is not just a pointer to a node.
typedef struct Node_tag { int value; struct Node_tag *next; struct Node_tag *prev } Node, *NodePtr;
typedef struct IntList_tag { NodePtr front; NodePtr back; } IntList;
// Creates an empty list.
void ListInitialize( IntList *pList ) { pList->front = NULL; pList->back = NULL; }
void ListPushFront( IntList *pList, int value )
{ NodePtr newNode = malloc(sizeof(Node));
if(NULL != newNode )
{ newNode->next = pList->front;
newNode->prev = NULL; newNode->value = value;
pList->front = newNode;
if( pList->back == NULL ) pList->back = newNode; // first element...
}
}
// ...
Eventually, using those functions, you can write splitlist() function in a concise and noise-free way:
void splitlist( IntList * source, IntList *target1, IntList *target2 )
{
IntList * currentTarget = target1;
for( NodePtr currentNode = ListGetFirstNode(source); currentNode != NULL; currentNode = ListGetNextNode(currentNode) )
{
ListPushBack(currentTarget, currentNode->value );
if(currentTarget == target1 ) currentTarget = target2;
else currentTarget = target1;
}
}
It might appear that it is much work to create all those other list functions if all you want is splitlist. But in real world applications you will most likely want all those other functions as well (or you have them already). Only in homework situations, this looks a bit funny.
Example code. Using typedef for node to be compatible with Microsoft C compilers (C89). Note sometimes the pointer to a circular list is a pointer to the last node of the circular list, (which contains a pointer to the first node of the circular list), allowing for faster appends. This example assumes list pointers are pointers to first nodes, but could be modified to assume list pointers are to last nodes.
#include <stdlib.h>
typedef struct _node{
struct _node *next;
int data;
}node;
node * splitlist(node * psrc, node ** ppdst1, node ** ppdst2)
{
node *ps = psrc;
node ** ppd1 = ppdst1;
node ** ppd2 = ppdst2;
*ppd1 = *ppd2 = NULL;
if(ps == NULL)
return NULL;
while(1){
*ppd1 = ps;
ps = *(ppd1 = &(ps->next));
if(ps == psrc)
break;
*ppd2 = ps;
ps = *(ppd2 = &(ps->next));
if(ps == psrc)
break;
}
*ppd1 = *ppdst1;
*ppd2 = *ppdst2;
return NULL;
}
main()
{
node a[8] = {{&a[1],0},{&a[2],1},{&a[3],2},{&a[4],3},
{&a[5],4},{&a[6],5},{&a[7],6},{&a[0],7}};
node *pa = &a[0];
node *pb = NULL;
node *pc = NULL;
pa = splitlist(pa, &pb, &pc);
return 0;
}

New with nodes in C, how to fix the struct?

I have problems with understanding the whole concept of this. The major issue that confuses me is the the pointer inside a struct inside a struct... Basically what I understand is that I am wanting to create a chain of nodes.
When I run this program it crashes after two seconds. I believe there is something wrong with my structure in main.c, because I have created it by myself and as you can see I am really Bambi on thin ice over here...
main.c
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "list.h"
// I guess my struct is not correct
static struct {
LIST node;
int item;
} node;
int main() {
list_create();
list_append(node.node, node.item);
}
list.h
typedef struct node* LIST;
LIST list_create (void);
void list_append (LIST l, int item);
list.c
struct node* list_create() {
struct node* head = (struct node*) malloc(sizeof (struct node));
head->next = NULL;
return head;
}
void list_append(struct node* n, int item)
{
/* Create new node */
struct node* new_node = (struct node*) malloc (sizeof (struct node));
new_node->item = item;
/* Find last link */
while (n->next) {
n = n->next;
}
/* Joint the new node */
new_node->next = NULL;
n->next = new_node;
}
At first, node is use for create a structure with data and in THIS data you have a pointer to another struct.
static struct {
LIST node;
int item;
} node;
Actually your structure is incorrect.
You must create at beginning a structure with your data for example :
static struct node{
int item;
};
then put a pointer to the similar structure but will not have same data =>
static struct node{
struct node *next;
int item;
};
You will can use this pointer to manipulate other & other structure.
I see another problem in your main :
You call the function "list_create()" which return a pointer to structure but you assign nothing.
you must create a pointer to struct then assign it like this :
int main() {
struct node *list;
list = list_create();
}
This code works completely (you can put it all in one C file; annotations in the code):
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
/* I removed the "static", because what we want is a type,
not a global static variable */
/* This "node" is our list-element. It has a pointer to a next element, and
some data, in this case, an int. */
typedef struct node {
struct node *next;
int item;
} node;
/* For convenience, another type, a pointer to a node. */
typedef node *LIST;
/* Creating a list is as simple as creating a node, and make the "next"
pointer NULL, you got this correct. */
struct node* list_create() {
struct node* head = (struct node*) malloc(sizeof (struct node));
head->next = NULL;
return head;
}
/* Nothing wrong in this append code. */
void list_append(struct node* n, int item)
{
/* Create new node */
struct node* new_node = (struct node*) malloc (sizeof (struct node));
new_node->item = item;
/* Find last link */
while (n->next) {
n = n->next;
}
/* Joint the new node */
new_node->next = NULL;
n->next = new_node;
}
/* I added this to make sure it works :) */
void print_list(LIST l) {
LIST tmp = l;
while (tmp) {
printf("%d\n", tmp->item);
tmp = tmp->next;
}
/* Here are some changes. I create a local LIST (which is basically a pointer
to a node, remember?) and use list_create to initialise it. Then, I call
list_append two times to put some extra data into it.
Works perfectly! */
int main() {
LIST myList = list_create();
list_append(myList, 10);
list_append(myList, 13);
print_list(myList);
}
You are calling list_create, but not using its result.

Why is memory being leaked in my C reverse list function?

I'm fairly new to Pointers and the memory model so excuse me if this is obvious, but I am writing a program to test a function reverse that reverses a list. Anyway I have it in three files, C5.c, C5-driver.c, and C5.h. Here they are in that order:
#include "C5.h"
#include <stdlib.h>
#include <stdio.h>
struct node *cons(int fst, struct node *rst) {
struct node *new = malloc(sizeof(struct node));
if (new == NULL) {
printf("cons: out of memory\n");
abort();
}
(*new).first = fst; /* same as (*new).first = fst */
(*new).rest = rst;
return new;
}
struct node *reverse(struct node *lst) {
struct node *ans = NULL;
while (lst != NULL) {
ans = cons((*lst).first, ans);
lst = (*lst).rest;
}
return ans;
}
void free_list(struct node *lst) {
struct node *p;
while (lst != NULL) {
p = lst->rest;
free(lst);
lst = p;
}
}
void print_list(struct node *lst) {
printf("( ");
while (lst != NULL) {
printf("%d ", (*lst).first);
lst = (*lst).rest;
}
printf(")\n");
}
C5-driver.c
#include <stdlib.h>
#include <stdio.h>
#include "C5.h"
int main() {
struct node *lst1 = cons(5, NULL);
struct node *lst2 = cons(3, lst1);
struct node *lst3 = cons(1, lst2);
print_list(lst3);
lst3 = reverse(lst3);
print_list(lst3);
free_list(lst3);
}
C5.h
struct node {
int first;
struct node *rest;
};
struct node *cons(int ,struct node *);
struct node *reverse(struct node *);
void print_list(struct node *);
void free_list(struct node *);
However I'm told by XCode that there are memory leaks.
I'm assuming it's after cons is used however I've tried creating a new struct node *ans = new and free(new); with return ans; but that doesn't work. I've also tried free_list as you can see above.
Thanks~
The reverse function calls cons which allocates memory, then it overwrites the lst3 pointer. The memory leak is that lst3 is overwritten which makes it impossible to recover that memory.
You should probably make a new variable like struct node *lst3_reverse and lst3_reverse = reverse(lst3). Then you can safely do free_list(lst3) and free_list(lst3_reverse) to free the memory.

Resources