I can't create doubly linked list properly in C - c

My list head always points to tail. What's the problem?
My linked_list.h:
#ifndef LINKED_LIST
#define LINKED_LIST
struct node
{
char *data;
struct node *nextElement;
struct node *prevElement;
};
void createList(struct node **head, struct node **tail);
void fill_list (char *word, struct node **head, struct node **tail);
#endif
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
#include <string.h>
int main()
{
FILE *dataFile;
char *word = (char *) calloc ( 255, sizeof(char) );
/* Create empty list */
struct node *head, *tail;
createList (&head, &tail);
/*------------------------*/
/* Data file open*/
dataFile = fopen("data.txt" ,"r");
if( dataFile == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
/* Data reading */
while (( fscanf(dataFile, "%s", word) ) != EOF )
{
int i = 0;
int wordsCount = 0;
for (i = 0; i <= strlen(word); i++)
{
if ( (word[i] >= 'a') && (word[i] <= 'z') )
wordsCount = wordsCount + 1;
}
if ( wordsCount == strlen(word) )
{
fill_list ( word, &head, &tail );
}
}
fclose(dataFile);
return 0;
};
and linked_list.c:
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
void createList(struct node **head, struct node **tail)
{
*head = NULL;
*tail = NULL;
}
void fill_list ( char *word, struct node **head, struct node **tail )
{
struct node *elem, *temp;
if ( (*head) == NULL )
{
// printf("HEAD = NULL\n");
elem = (struct node *) malloc ( sizeof (struct node) );
elem -> data = word;
elem -> nextElement = NULL;
elem -> prevElement = NULL;
(*head) = elem;
*tail = elem;
// printf("%s\n", (*head) -> data );
}
else
{
// printf("HEAD != NULL\n");
elem = (struct node *) malloc ( sizeof (struct node) );
elem -> data = word;
elem -> nextElement = NULL;
elem -> prevElement = *tail;
*tail = elem;
// printf("%s\n", (*head) -> data );
}
}
My data file: qw erty b cc.
Firstly, head == NULL, so head -> data = 'qw' and it should be as head all the time, but it changes to erty, then b and cc after every loop step.
What I'm doing wrong?

The problem is that you use the same string for all input, and you use that for all nodes. This means all nodes will have its data member point to the same string. This string will of course only contain what you last read into it.
You may want to keep the string buffer in main as a normal array (instead of allocating it on the heap) and use e.g. strdup to duplicate the string for the nodes. Don't forget to free them later though.
A pointer is exactly what it sounds like, it's a variable that points to some other place in memory. You can have many pointers all pointing to the same memory.
In your case you pass the pointer word in the function main to all our calls to fill_list. This means that all nodes you create in fill_list will use the exactly same pointer, and they will all point to the exact same memory.
This means that all nodes in your list will have the data member seem to be the same value and it will always be the last string read into word in the main function.
If you use a function such as strdup it will duplicate the string. I.e. it will allocate completely new memory for the string and copy from the old area into the newly allocate area, and return a pointer to the newly allocated memory.

try this
void fill_list ( char *word, struct node **head, struct node **tail )
{
struct node *elem, *temp;
/* you need to create node first ! */
elem = (struct node *) malloc ( sizeof (struct node));
elem -> data = NULL ;
elem -> data = (char*) malloc( sizeof(char)*255));
if ( elem -> data == NULL )
{
perror("alloc data failed ");
}
if ( (*head) == NULL )
{
// printf("HEAD = NULL\n");
/* call memcpy() function need to #include <string.h> */
elem -> data = memcpy((void*)elem -> data,(void*)word,strlen(word));
elem -> nextElement = NULL;
elem -> prevElement = NULL;
(*head) = elem;
*tail = elem;
// printf("%s\n", (*head) -> data );
}
else
{
// printf("HEAD != NULL\n");
elem -> data = memcpy((void*)elem -> data,(void*)word,strlen(word));
elem -> nextElement = NULL;
elem -> prevElement = *tail;
*tail = elem;
// printf("%s\n", (*head) -> data );
}

Related

linked list problem when displaying the list in C

having segmentation error while trying to access nodes
i can create new nodes with my add function after function executes i cant access my nodes. i think they deallocated in memory but i couldnt figure it out.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *nextNode;
};
struct node *head;
void add(int data)
{
struct node *new = (struct node *)malloc(sizeof(struct node));
new->data = data;
new->nextNode = NULL;
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
printf("\nValue of temp1:%d\nValue of new: %d\n",temp1,new);
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
void printList()
{
int i = 1;
struct node *tempP;
tempP = head;
while (tempP != NULL)
{
printf("\nData of %dth element is : %d\n", i, tempP->data);
tempP = tempP->nextNode;
i++;
}
}
void main()
{
head = (struct node *)malloc(sizeof(struct node));
head->data = 10;
head->nextNode = NULL;
add(20);
add(30);
add(40);
printList();
}
This code snippet within the function add
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
is wrong. Within it there is changed the local variable temp1. It is not linked with the list.
Also using the conversion specifier %d to output a pointer invokes undefined behavior. You should use conversion specifier %p.
Using your approach to the function definition you could write instead.
void add(int data)
{
struct node *new = malloc( sizeof( *new ) );
new->data = data;
new->nextNode = NULL;
if ( head == NULL )
{
head = new;
}
else
{
struct node *temp1 = head;
while ( temp1->nextNode != NULL)
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new;
}
printf("\nValue of temp1->nextNode:%p\nValue of new: %p\n",
( void * )temp1->nextNode, ( void * )new);
printf("\nData of temp1->nectNode:%d\nData of new:%d\n",
temp1->nextNode->data,new->data);
}
Pay attention to that it is a bad design when functions depend on a global variable as in your case where the functions depend on the global variable head.
And it is also a bad idea when the first node is added to the list bypassing the function add.
And you need check whether a node was successfully allocated.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )
As for me I would declare the pointer to the head node in main like
int main( void )
{
struct node *head = NULL;
// ...
And the function add will look like
int add( struct node **head, int data )
{
struct node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->nextNode = NULL;
while ( *head != NULL ) head = &( *head )->nextNode;
*head = new_node;
}
return success;
}
and called like
struct node *head = NULL;
add( &head, 10 );
add( &head, 20 );
add( &head, 30 );
add( &head, 40 );
In turn the function printList can look like
void printList( const struct node *head )
{
for ( size_t i = 1; head != NULL; head = head->nextNode )
{
printf( "Data of %zuth element is : %d\n", i++, head->data);
}
}
And you need at least to write one more function that will free all the allocated memory.
There were a handful of mistakes in your add() function, which I've highlighted and fixed below:
void add(int data)
{
struct node *new = malloc(sizeof(*new)); // suggested by ryyker
new->data = data;
new->nextNode = NULL;
struct node *temp1 = head; // just keep it short
while (temp1->nextNode != NULL) // temp1 != NULL will always result in it being NULL, last node is the node with NULL as next
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new; // you want the next in the list to be the new node, not reassign the head to a new node. That's a memory leak.
// remember: temp1 == head, and head = new makes head lose the original node and point to the newly created one
printf("\nValue of temp1:%p\nValue of new: %p\n",temp1,new); // %p for pointers
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
Output:
Value of temp1:0x55809a4b22a0
Value of new: 0x55809a4b22c0
Data of temp1:10
Data of new:20
Value of temp1:0x55809a4b22c0
Value of new: 0x55809a4b26f0
Data of temp1:20
Data of new:30
Value of temp1:0x55809a4b26f0
Value of new: 0x55809a4b2710
Data of temp1:30
Data of new:40
Data of 1th element is : 10
Data of 2th element is : 20
Data of 3th element is : 30
Data of 4th element is : 40

Copy a pointer to a struct in a function (linked list)

I want to craete a single linked list without gloabal variables. I initialized the first element with NULL and then wanted to copy the first element node to list_. It is copied in the function but the side effect isnĀ“t working. In my main-function the value is still NULL.
If I return the struct in the add_element()function all works fine but, is it possible that l gets the value of node without changing the functions structure and the struct itself?
#include <stdio.h>
#include <stdlib.h>
struct list {
int value;
struct list *next;
};
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
int add_element(struct list *list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(list_ == NULL)
{
list_ = node;
printf("list_->value = %d\n", list_->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(l,&i);
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); // does not work, l is NULL
return 0;
}
kaylum's comment points you in the right direction.
When you pass a pointer in C, the pointer's value is copied to the stack, and this copy is the value that the add_element() function is referring to. When you alter the pointer's value, you are modifying the copy placed on the stack, not the original pointer.
If you want to alter the original pointer (as if it was passed by reference and not by value) you need to use a double pointer.
Try this variant:
int add_element(struct list **list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(*list_ == NULL) // dereferencing the double pointer will access the original pointer
{
*list_ = node; // this will change the original pointer
printf("(*list_)->value = %d\n", (*list_)->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(&l,&i); // notice you are now passing the address of l instead of its value
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); //should work now
return 0;
}
For starters the function initialize
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
does not make great sense. You can just write in main
struct list *l = NULL;
Or the function initialize can look like
inline struct list *initialize(void)
{
return NULL;
}
The function add_element deals with a copy of the passed list.
int add_element(struct list *list_, void *v);
So any changes of the copy do not influence on the original list. Also it is unclear why the second parameter has the type void * instead of the type int.
You have to pass the list by reference to the function.
The function can look the following way
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
and called for example like
int i = 10;
if ( !add_element( &l, i ) )
{
puts( "Error: not enough memory." );
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct list
{
int value;
struct list *next;
};
static inline struct list * initialize( void )
{
return NULL;
}
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
void output( struct list *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->value );
}
puts( "NULL" );
}
int main(void)
{
struct list *head = initialize();
const int N = 10;
for ( int i = 0; i < N; i++ )
{
add_element( &head, i );
}
output( head );
return 0;
}
Its output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
Pay attention to that if a new node is appended to the tail of the list then it is better to define the list as a two-sided singly-linked list.

Node Insertion,Linked Lists

I have this code through which it inserts node at the starting.This code also contains a function which prints linked list and if empty it prints linked list is empty .
when i run this code , i have my ouput as Linked list is empty .
struct node {
int data;
node* next;
}* start = NULL;
void append(node* linkedlist, int data)
{
node* new_element = NULL;
new_element = (node*)malloc(sizeof(struct node));
new_element->data = data;
if (linkedlist == NULL) {
linkedlist = new_element;
new_element->next = NULL;
}
else {
new_element->next = (linkedlist)->next;
(linkedlist)->next = new_element;
}
}
int main()
{
append(start, 4);
append(start, 5);
printList(start);
}
Update:
void printList(node* linkedlist)
{
node* ptr = linkedlist;
if (linkedlist == NULL) {
printf("Linked list is empty");
exit(0);
}
else {
while (ptr != NULL) {
cout << ptr->data;
ptr = ptr->next;
}
}
}
What could i be possibly doing wrong? What should i change in order to make it work?
Your problem is here linkedlist = new_element; When passing arguments to a function they are passed by value. Even when you pass a pointer you are actually passing a copy of that pointer(you can verify by printing the address of linkedlist inside the function and outside the function). The statement linkedlist = new_element; assigns the new_element to a copy. Once the function return you end up with nothing (and a memory leak). Remember when you need to change a pointer itself you must use a double pointer **
You put in the value of start which points to null. Then you copy it to another pointer linkedlist and set it to a new value. After the function start is still pointing to null though because you never changed the value of start.
You could try to change your declaration to
void append(node *&linkedlist,int data)
If you are using a c++ compiler.
else
void append(node **linkedlist,int data)
...
append(&start,4);
if you are using C
For starters the code you showed is not valid C code. You are using C++ elements. So the program will not even compile as a C program.
As the node start that is initially set to NULL can be changed by the function you have to pass it by reference. Otherwise the function parameter linkedlist is a local variable of the function that will be changed in the function and at last will be destroyed after exiting the function. So the original pointer start itself will not be changed.
Also this else code block
else {
new_element->next = (linkedlist)->next;
(linkedlist)->next = new_element;
}
is wrong. This code block does not insert a new node in the beginning of the list. It inserts a new node after the first already existent node.
Take into account that the function name append is not suitable for inserting a node in the beginning of the list. It would be better to name it like insert.
The function can look the following way
int insert( struct node **linkedlist, int data )
{
struct node *new_element = malloc( sizeof( struct node ) );
int success = new_element != NULL;
if ( success )
{
new_element->data = data;
new_element->next = *linkedlist;
*linkedlist = new_element;
}
return success;
}
If you indeed need a function that appends nodes to the list then it can look the following way
int append( struct node **linkedlist, int data )
{
struct node *new_element = malloc( sizeof( struct node ) );
int success = new_element != NULL;
if ( success )
{
new_element->data = data;
new_element->next = NULL;
while ( *linkedlist != NULL ) linkedlist = &( *linkedlist )->next;
*linkedlist = new_element;
}
return success;
}
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
struct node
{
int data;
struct node* next;
} *start = NULL;
int insert( struct node **linkedlist, int data )
{
struct node *new_element = malloc( sizeof( struct node ) );
int success = new_element != NULL;
if ( success )
{
new_element->data = data;
new_element->next = *linkedlist;
*linkedlist = new_element;
}
return success;
}
int append( struct node **linkedlist, int data )
{
struct node *new_element = malloc( sizeof( struct node ) );
int success = new_element != NULL;
if ( success )
{
new_element->data = data;
new_element->next = NULL;
while ( *linkedlist != NULL ) linkedlist = &( *linkedlist )->next;
*linkedlist = new_element;
}
return success;
}
void printList( struct node* linkedlist )
{
if ( linkedlist == NULL )
{
puts( "Linked list is empty" );
}
else
{
for ( struct node *current = linkedlist; current != NULL; current = current->next )
{
printf( "%d ", current->data );
}
printf( "\n" );
}
}
int main( void )
{
const int N = 10;
for ( int i = 1; i <= N; i++ )
{
if ( i % 2 == 0 ) append( &start, i );
else insert( &start, i );
}
printList( start );
return 0;
}
Its output is
9 7 5 3 1 2 4 6 8 10
I dont think your if statement is correct. I would do it like this
if(linkedlist == null)
{
//head node is null i.e, linked list is empty hence make the new node as head node
linkedlist = new_element;
}else{
//make the new node point to the head
new_element->next = linkedlist;
//make the new node as head node
linkedlist = new_element;
}
In the append function you should
First initialise next of newnode to be null
Check before inserting for empty list, if empty then then make this as head.
If it is not empty then make the new node point to the head of your list and make it the new head.
To reflect back the insertion done in append you should return the modified head from the function(Also modify main accordingly).
Look at this code:-
node *append(node *linkedlist,int data){
node *new_element=NULL;
new_element=(node *)malloc(sizeof(struct node));
new_element->data=data;
new_element->next=NULL;// initialise next of newnode to be null here
// In case of empty list make this as first node
if(linkedlist==NULL)
{
linkedlist=new_element;
}
else
{
new_element->next=(linkedlist);//point the new node to head of list
(linkedlist)=new_element;// make new node as head
}
return linkedlist;
}
int main()
{
start = append(start, 4);
start = append(start, 5);
printList(start);
}
When you pass a parameter in C, it creates a local copy for the function to use. When you modify the parameter inside the function, it only changes the local copy.
void f1( int a )
{
a = 1; // modification does not affect the calling function
}
int b=0;
f1( b );
assert( b == 0 ); // b was not changed by f
In C (or C-style C++), if you want a function to modify a parameter, you need to pass it as a pointer:
void f2( int * a )
{
(*a) = 1;
}
int b=0;
f2( &b );
assert( b == 1 ); // b was changed by f
If that parameter was already a pointer type, then you need to pass it as a pointer to a pointer:
void f3( int * * a )
{
(*a) = (int*) malloc(sizeof(int));
(**a) = 1;
}
int * b = NULL;
f3( &b );
assert( b != NULL ); // the pointer was initialized
assert( *b == 1 ); // the pointed-to value was initialized
The assignment process can be a bit simpler in C++ because you can use reference parameters instead of explicitly specifying the pointer.

C - Linked Lists - Deleting Head - Segmentation Fault

I am working on a problem for a class and we're learning linked lists in C. I was given a section of code to complete, specifically the delete a node section and I'm having a problem deleting head. Every time I try to delete head I receive a segmentation fault. Can someone tell me what I'm doing wrong?
EDIT2
My teacher wrote everything but the lookup and delete functions.
I have fixed the glaring errors pointed out by the gentleman from Moscow and Mr. Petriuc, however the code still doesn't run. It does compile, but there is still a problem in head.
Here is the full code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "linkedList.h"
// keep an unsorted array of char *'s, strings.
/*
Create an empty node, return 0 if fail, 1 if succeed
*/
struct node * createNode() {
struct node *p = (struct node *) malloc(sizeof(struct node));
if (p == NULL) return 0;
p->prev = p->next = NULL;
p->data = NULL;
}
/*
Lookup string in the list, return pointer to node of first occurence, NULL if not found.
*/
struct node * lookup(struct node *head, char *s) {
struct node *p;
for(p=head; p!=NULL; p=p->next){
if(strcmp(s,p->data)==0){
return p;
}
// just like print, but check if strcmp(s, p->data) == 0, and if so then return p
}
return NULL;
}
/*
Insert new string into the linked list, return 1 if success, 0 if fail.
*/
int insert(struct node **head, char *newS, int insertDuplicate) {
struct node *p = lookup(*head, newS);
if (p == NULL || insertDuplicate) {
// create a new node, put it at the front.
p = createNode();
if (p == NULL) return 0;
// put the string in the new node
p->data = (char *) malloc(sizeof(char) * (1 + strlen(newS)));
if (p->data == NULL) return 0;
strcpy(p->data, newS);
// note: make changes and use old head before setting the new head...
p->next = *head; // next of new head is previous head
if (*head != NULL)
(*head)->prev = p; // previous of old head is new head
*head = p; // set the new head
}
return 1;
}
/*
Remove string from list if found, return 1 if found and deleted, 0 o/w.
*/
int delete(struct node **head, char *s) {
struct node *p,*pr,*ne;
// first do a lookup for string s, call lookup.
p=lookup(*head, s);
if(p==*head){
*head = p->next;
free(p);
return 1;
}
if(p!=NULL){
printf("%s",p);
pr = p->prev;
ne = p->next;
free(p->data);
free(p);
if(pr==NULL||ne==NULL){
return 0;
}
pr->next=ne;
ne->prev=pr;
// if lookup returns NULL, done, return 0.
// if lookup returns p, not NULL,
// pr = p->prev, ne = p->next
// set pr->next to ne, ne->prev to pr
// but what if pr or ne is NULL
// and note that we need node **head because if delete head,
// need to update head pointer back in calling function, in
// here if you want head probably do *head. like in insert.
// also, before the pointer to the one you're deleting is gone,
// free p->data and p.
return 1;
}
return 0;
}
void print(struct node *head) {
struct node *p;
for(p = head; p != NULL ; p = p->next) {
printf("%s\n", p->data);
}
}
You are doing
p->next = *head;
But p is not assigned anywhere.
Your function does not make sense. You call the function lookup three times.
Moreover you use pointers that were not initialized like for example
p->next = *head;
or
printf("%s",p);
pr = p->prev;
ne = p->next;
The function can be written the following way
int delete( struct node **head, char *s )
{
int success;
struct node *target = lookup( *head, s );
if ( ( success = target != NULL ) )
{
if ( target->prev != NULL )
{
target->prev->next = target->next;
}
else
{
*head = target->next;
}
if ( target->next != NULL )
{
target->next->prev = target->prev );
}
free( target );
}
return success;
}
Take into account that the second parameter of the function and the corresponding parameter of the function lookup should be declared with qualifier const
int delete( struct node **head, const char *s ) ;
^^^^^
struct node * lookup( struct node *head, const char *s );
^^^^^^
Simplified delete() function. I inlined lookup() because the function as it is is worthless (you need a pointer to pointer, not a pointer to act upon)
/*
Remove string from list if found, return 1 if found and deleted, 0 o/w.
*/
int delete(struct node **head, char *s) {
struct node *tmp;
// first do a lookup for string s, no need to call call lookup.
for( ;*head; head = &(*head)->next ){
if (!strcmp( (*head)->data, s)) break;
}
if (!*head) return 0; // not found
tmp = *head
*head = tmp->next
free(tmp);
return 1;
}

Segmentation error for linked list

My execution's name is test4.
Input:
$ ./test4 cccc zz abcdef0123456789 aaabbbcccddd
I expect to create a linked list of type char* as follow:
---> 12:aaabbbcccddd ---> 12:abcdef0123456789 ---> 2:zz ---> 4:cccc
each node has the form of "n:a" (n is the length of string a, n <= 12, if the length of a is more than 12 then n = 12)
Below is my code:
struct Node *prepend(struct Node *list, char *s)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL)
return NULL;
int length_s = strlen(s);
if (length_s > 12)
length_s = 12;
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
strcpy(node->data, temp);
node->next = list;
return node;
}
prepend function links a new node to list
struct Node {
struct Node *next;
char *data;
};
int main(int argc, char **argv)
{
struct Node *list = NULL;
argv++;
while (*argv)
{
list = prepend(list,*argv);
argv++;
}
return 0;
}
Assume all necessary libraries and struct are included, I keep getting a segmentation error when running the code. How do I fix it? I believe the problem is in sprintf but can't figure out why.
You don't allocate memory for temp here:
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
You could use either a static array of chars or dynamically allocate the memory for it.
In order to copy what you want, you should so this:
If data of Node is a char*,
node->data = malloc((length_s + 1) + 1 + digits_of_length);
sprintf(node->data,"%d:%s", length_s, s);
If data of Node is an array of chars, you should do this:
sprintf(node->data,"%d:%s", ((length_s + 1) + 1 + digits_of_length), s);
As you see this gets a bit nasty, because you have to find the digits of the length too, in order to allocate memory.
Why not augmenting your Node with an extra field called str_length, which will keep track of the length of the string the current node holds. That way, you could modify your function to this:
struct Node *prepend(struct Node *list, char *s)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL)
return NULL;
int length_s = strlen(s);
node->data = malloc(length_s + 1);
strcpy(node->data, temp);
node->str_length = length_s + 1;
node->next = list;
return node;
}
When you go trhough this, don't forget to write a free_list(), which will de-allocates the whole list.
Also, don't cast what malloc returns. Why?
The problem is in these statements
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
You did not allocate memory that will be pointed to by poointer temp. Sp the program has undefined begaviour.
You could make your life simpler if instead of the pointer in your structure you would use an array of size 12 + 1 because the length of copied strings is limited by 12 characters.
For example
enum { size = 13 };
struct Node
{
char data[size];
Node *next;
};
//...
struct Node *prepend( struct Node *list, const char *s )
{
struct Node *node = ( struct Node * )malloc( sizeof( struct Node ) );
if ( node == NULL ) return list;
strnspy( node->data, s, size );
node->data[size - 1] = '\0';
node->next = list;
return node;
}
If you need to use a pointer instead of a character array and sprintft instead of strncpy hen you can write
struct Node *prepend( struct Node *list, const char *s )
{
const size_t N = 12;
struct Node *node = ( struct Node * )malloc( sizeof( struct Node ) );
if ( node == NULL ) return list;
node->data = malloc( ( N + 1 ) * sizeof( char ) );
sprintf( node->data, "%*.*s", N, N, s );
node->next = list;
return node;
}
When the list will not be needed any more you have to delete it. For example
void delete( struct Node *list )
{
while ( list )
{
Node *tmp = list;
list = list->next;
free( tmp->data );
free( tmp );
}
}

Resources