How to create an empty doubly-linked list in C? - c

I wrote most of the code for my doubly linked list in C, but it seems that the reason I'm struggling to add values into the list is due to a mistake I made when creating an empty doubly linked list. Here's my attempt at it, what am I doing wrong here and how would I go about fixing it?
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list
{
struct node head;
} List;
// The type for a list position.
typedef struct list_pos
{
struct node *node;
} ListPos;
List *list_create(void)
{
List *lst = (List*)malloc(sizeof(List));
if(lst == NULL)
{
printf("No more memory!\n");
return 0;
}
return lst;
}
static struct node *make_node(const char *value)
{
struct node *result = malloc(sizeof(struct node));
result->value = strdup(value);
result -> next = NULL;
result -> prev = NULL;
return result;
}
Example usage: main function: List *lst = list_create(); from function add_values():
static void add_values(List *lst) {
char str[2] = "A";
ListPos pos = list_first(lst);
for (char ch = 'A'; ch <= 'Z'; ch++) {
str[0] = ch;
pos = list_insert(pos, str);
pos = list_next(pos);
}
}
Implementation of functions:
int main(void){
List *lst = list_create();
...
}
add_values static void add_values(List *lst) {
char str[2] = "A"; ListPos pos = list_first(lst);
for (char ch = 'A'; ch <= 'Z'; ch++) {
str[0] = ch;
pos = list_insert(pos, str);
pos = list_next(pos);
}
}

Related

Values aren't being saved in a queue in C

I'm trying to implement a queue in C using a linked list. I ran my code through a C visualizer and it seems that the values A-E aren't being saved. As in, one node will contain the letter A then when queue_enqueue is called again, another node is created that holds the letter B and then the previous node that contained A just, disappears... My code contains other functions like dequeue and one to check if the queue is empty, but I took them out to keep my code short and they are independent of the functions provided here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct node {
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list {
struct node head;
} List;
typedef struct queue {
List *list;
} Queue;
Queue *queue_create(void) {
Queue *q = (Queue*)malloc(sizeof(struct queue));
List *ptr = (List*)malloc(sizeof(struct list));
q->list = ptr;
q->list->head.next = NULL;
return q;
}
void queue_destroy(Queue *q) {
free(q->list->head.value);
free(q);
}
void queue_enqueue(Queue *q, const char *value) {
struct node *temp;
temp = malloc(sizeof(struct node));
temp->value = strdup(value);
temp->next = NULL;
q->list->head.next = temp;
q->list->head.value = temp;
}
int main(void) {
// Create an empty queue.
Queue *q = queue_create();
// Add the values A, B, ..., Z to the queue.
char str[] = "A";
for (char ch = 'A'; ch <= 'E'; ch++) {
str[0] = ch;
queue_enqueue(q, str);
}
// Clean up.
queue_destroy(q);
return 0;
}
To simplify your problem you should begin with a single-linked list and in your example there is no need to use char* as node value:
struct node {
struct node* next;
char value;
};
You also might want to add a element counter for your list:
typedef struct list {
struct node *head;
size_t num;
}
and a function to create a new node with the given value:
struct node *node_create(char value) {
struct node *nd = malloc(sizeof(struct node));
if (nd)
nd->value = value;
return nd;
}
The magic happens in the insert function but it is no rocket science at all. You either create your new node where head is pointing (empty list) or at the end of the list.
void list_insert(List *list, char value) {
if (!list)
return;
if (!list->head) {
// first element of list
list->head = node_create(value);
if (list->head)
list->num++;
}
else {
// move to the end of the list
struct node *nd = list->head;
while (nd->next) {
nd = nd->next;
}
nd->next = node_create(value);
if (nd->next)
list->num++;
}
}
Also make sure to properly initialize your list with some list_create function and when cleaning the list take care to free all list elements before releasing the memory of the list itself
You are not linking the chain pointers correctly.
And, setting q->list->head.value = temp; won't even compile.
For a doubly linked list, reusing a node struct as the front/back pointers (e.g prev/next) is doable but unclear. Better to redefine List slightly to use front/back--it's clearer.
Your destroy code is also wrong.
When appending to a list, the first time is slightly different than subsequent ones.
Here's the refactored code.
Since your code didn't change any of the list's next/prev pointers or temp's next/prev pointers, it wasn't clear whether you wanted to enqueue to the front or the back of the list, so I added both functions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct node {
struct node *next;
struct node *prev;
char *value;
};
// The type for a list.
typedef struct list {
struct node *front;
struct node *back;
size_t count;
} List;
typedef struct queue {
List *list;
} Queue;
Queue *
queue_create(void)
{
Queue *q = malloc(sizeof(*q));
q->list = calloc(1,sizeof(List));
return q;
}
void
queue_destroy(Queue *q)
{
List *list = q->list;
struct node *cur;
struct node *next;
if (list != NULL)
cur = list->front;
else
cur = NULL;
for (; cur != NULL; cur = next) {
next = cur->next;
free(cur->value);
}
free(list);
free(q);
}
struct node *
node_create(const char *value)
{
struct node *temp = calloc(1,sizeof(*temp));
temp->value = strdup(value);
return temp;
}
void
queue_enqueue_front(Queue *q,const char *value)
{
struct node *temp = node_create(value);
List *list = q->list;
temp->next = list->front;
if (list->front != NULL)
list->front->prev = temp;
list->front = temp;
if (list->back == NULL)
list->back = temp;
list->count += 1;
}
void
queue_enqueue_back(Queue *q,const char *value)
{
struct node *temp = node_create(value);
List *list = q->list;
temp->prev = list->back;
if (list->back != NULL)
list->back->next = temp;
list->back = temp;
if (list->front == NULL)
list->front = temp;
list->count += 1;
}
void
queue_print_fwd(Queue *q,const char *who)
{
List *list = q->list;
struct node *cur;
if (who != NULL)
printf("%s:\n",who);
for (cur = list->front; cur != NULL; cur = cur->next)
printf(" %s\n",cur->value);
}
void
queue_print_rev(Queue *q,const char *who)
{
List *list = q->list;
struct node *cur;
if (who != NULL)
printf("%s:\n",who);
for (cur = list->back; cur != NULL; cur = cur->prev)
printf(" %s\n",cur->value);
}
int
main(void)
{
// Create an empty queue.
Queue *q = queue_create();
// Add the values A, B, ..., Z to the queue.
char str[] = "A";
for (char ch = 'A'; ch <= 'E'; ch++) {
str[0] = ch;
queue_enqueue_back(q, str);
#ifdef DEBUG
queue_print_fwd(q,"pushback");
#endif
}
for (char ch = 'K'; ch >= 'F'; ch--) {
str[0] = ch;
queue_enqueue_front(q, str);
#ifdef DEBUG
queue_print_fwd(q,"pushfront");
#endif
}
queue_print_fwd(q,"Forward");
queue_print_rev(q,"Reverse");
// Clean up.
queue_destroy(q);
return 0;
}
Here's the program output:
Forward:
F
G
H
I
J
K
A
B
C
D
E
Reverse:
E
D
C
B
A
K
J
I
H
G
F
UPDATE:
Here's a slightly cleaned up version.
There's probably no need to allocate q->list--It could just be declared as List list; instead of List *list;
Just for grins, I also added a node removal function (e.g. queue_unlink).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct node Node;
struct node {
Node *next;
Node *prev;
char *value;
};
// The type for a list.
typedef struct list {
Node *front;
Node *back;
size_t count;
} List;
typedef struct queue {
List list;
} Queue;
Queue *
queue_create(void)
{
Queue *q = calloc(1,sizeof(*q));
return q;
}
void
queue_destroy(Queue *q)
{
List *list = &q->list;
Node *cur;
Node *next;
for (cur = list->front; cur != NULL; cur = next) {
next = cur->next;
free(cur->value);
list->count -= 1;
}
free(q);
}
void
queue_unlink(Queue *q,Node *cur)
{
List *list = &q->list;
do {
if (cur == NULL)
break;
Node *prev = cur->prev;
Node *next = cur->next;
if (prev != NULL)
prev->next = next;
if (next != NULL)
next->prev = prev;
if (list->front == cur)
list->front = next;
if (list->back == cur)
list->back = prev;
cur->prev = NULL;
cur->next = NULL;
list->count -= 1;
} while (0);
}
Node *
node_create(const char *value)
{
Node *temp = calloc(1,sizeof(*temp));
temp->value = strdup(value);
return temp;
}
void
queue_enqueue_front(Queue *q,const char *value)
{
Node *temp = node_create(value);
List *list = &q->list;
Node *front = list->front;
temp->next = front;
if (front != NULL)
front->prev = temp;
list->front = temp;
if (list->back == NULL)
list->back = temp;
list->count += 1;
}
void
queue_enqueue_back(Queue *q,const char *value)
{
Node *temp = node_create(value);
List *list = &q->list;
Node *back = list->back;
temp->prev = back;
if (back != NULL)
back->next = temp;
list->back = temp;
if (list->front == NULL)
list->front = temp;
list->count += 1;
}
int
queue_print_node(Node *cur,int totlen)
{
int curlen;
curlen = strlen(cur->value);
if ((totlen + curlen + 1) >= 78) {
fputc('\n',stdout);
totlen = 0;
}
fputc(' ',stdout);
totlen += 1;
fputs(cur->value,stdout);
totlen += curlen;
return totlen;
}
void
queue_print_fwd(Queue *q,const char *who)
{
List *list = &q->list;
Node *cur;
int totlen = 0;
if (who != NULL)
printf("%s:\n",who);
for (cur = list->front; cur != NULL; cur = cur->next)
totlen = queue_print_node(cur,totlen);
if (totlen > 0)
fputc('\n',stdout);
}
void
queue_print_rev(Queue *q,const char *who)
{
List *list = &q->list;
Node *cur;
int totlen = 0;
if (who != NULL)
printf("%s:\n",who);
for (cur = list->back; cur != NULL; cur = cur->prev)
totlen = queue_print_node(cur,totlen);
if (totlen > 0)
fputc('\n',stdout);
}
int
main(void)
{
// Create an empty queue.
Queue *q = queue_create();
// Add the values A, B, ..., Z to the queue.
char str[] = "A";
for (char ch = 'A'; ch <= 'E'; ch++) {
str[0] = ch;
queue_enqueue_back(q, str);
#ifdef DEBUG
queue_print_fwd(q,"pushback");
#endif
}
for (char ch = 'K'; ch >= 'F'; ch--) {
str[0] = ch;
queue_enqueue_front(q, str);
#ifdef DEBUG
queue_print_fwd(q,"pushfront");
#endif
}
for (int iter = 1; iter <= 10; ++iter) {
char buf[35];
int len = (rand() % (sizeof(buf) - 1)) + 1;
int idx = 0;
for (; idx < len; ++idx) {
int chr = (rand() % 26) + 'a';
buf[idx] = chr;
}
buf[idx] = 0;
queue_enqueue_back(q, buf);
}
queue_print_fwd(q,"Forward");
queue_print_rev(q,"Reverse");
// Clean up.
queue_destroy(q);
return 0;
}

Not able to add to the head of a Linked List

I've created a program that would insert a node into a linked list based on alphabetical order (A-Z). I'm able to do it, however, I'm not able to insert at the front of the linked list. We can assume that the list is never initially empty. Any help? Here is my code with the relevant structs. The problem is where // Inserting at the front of the list
typedef struct fileNode {
char *tokenName; // hi
double token; // 0.5
struct fileNode *next;
} fileNode;
typedef struct fileStruct {
char *name; // a.txt
int numberOfTokens; // 4
fileNode *tokenLL;
struct fileStruct *next;
} fileStruct;
void insertLL(struct fileNode *list, char *token){
struct fileNode *ptr = list;
struct fileNode *prev = NULL;
struct fileNode *newNode = malloc(sizeof(struct fileNode));
newNode->tokenName = token;
newNode->token = 1;
bool inserted = false;
while (ptr != NULL && inserted == false) {
if (strcmp(ptr->tokenName, token) > 0){
count++;
if (prev == NULL){ // Inserting at the front of the list
newNode->next = ptr;
ptr = newNode;
list = newNode;
inserted = true;
return;
}
else {
prev->next = newNode;
newNode->next = ptr;
inserted = true;
}
} // end of if
prev = ptr;
ptr = ptr->next;
} // end of while
if (!inserted){
prev->next = newNode;
} // adding to the end of the list
}
To modify the direct object pointed by *list , you need to declare it as a **list in your function arguments.
if you declare it as a *list you're going to modify the object *list only inside the function. It's because when you call a function the arguments used inside the called function are a copy of the variables used to call the function in the calling function.
#include <stdio.h>
void add(int x,int y){
x=y;
}
void add_ptr(int *x,int y){
*x=y;
}
int main(int argc, char *argv[]) {
int x=1;
int y=2;
add(x,y);
printf("add\t x:%d\n",x);
add_ptr(&x,y);
printf("add_ptr\tx:%d\n",x);
return 0;
}
if you declare it as a **list you're going to modify the object pointed at the adress pointed by **list when you set: *(list)=Newnode; (the change is going to be permanent )
void insertLL(struct fileNode **list, char *token){
struct fileNode *ptr = *list;
struct fileNode *prev = NULL;
struct fileNode *newNode = malloc(sizeof(struct fileNode));
newNode->tokenName = token;
newNode->token = 1;
bool inserted = false;
while (ptr != NULL && inserted == false) {
if (strcmp(ptr->tokenName, token) > 0){
count++;
if (prev == NULL){ // Inserting at the front of the list
newNode->next = *list; /*it's easier to understand with only *list*/
*list = newNode;
inserted = true;
return;
}
else {
prev->next = newNode;
newNode->next = ptr;
inserted = true;
}
} // end of if
prev = ptr;
ptr = ptr->next;
} // end of while
if (!inserted){
prev->next = newNode;
} // adding to the end of the list
}

How to populate a linked list with strings using new lines as delimiters?

I have the following linked list struct:
struct _node {
char *string;
struct _node *next;
}
struct _list {
struct _node *head;
struct _node *tail;
}
I want to write a function that takes in a string as input and uses newline characters as delimiters to populate the linked list with strings.
For example, if the input string was "First\nSecond\nThird\n", then the function
struct _list *newList(char text[]);
should return the following linked list:
[First]->[Second]->[Third]->NULL // this is correct
The function I wrote doesn't work properly because the linked list I get looks like this:
[First]->[Second]->[Third]->[]->NULL // this is wrong
Here is my function:
struct _list * newList(char text[]) {
int letterCount = 1;
int flag = 0;
int step = 0;
char currChar;
struct _list * newList = malloc(sizeof(struct _list));
assert(newList != NULL);
newList->head = NULL;
newList->last = NULL;
newList->size = 0;
while(flag != 1) {
currChar = text[letterCount];
if (currChar == '\n') {
struct _node * newNode = createNode(strlcpy(text,step,letterCount));
if(newList->head == NULL) {
newList->head = newNode;
}
else{
newList->last->next = newNode;
}
newList->last = newNode;
step += (letterCount-step) + 1;
}
else if (currChar == '\0') {
struct _node * newNode = createNode(strlcpy(text,step,letterCount));
if(newList->head == NULL) {
newList->head = newNode;
}
else {
newList->last->next = newNode;
}
newList->last = newNode;
flag = 1;
}
letterCount++;
}
return newList;
}
Another approach is using tokens:
struct _list * newList(char text[]){
struct _list * newList = NULL;
newList = malloc(sizeof(struct _list));
assert(newList != NULL);
newList->head = NULL;
newList->tail = NULL;
char *token = strtok(text, "\n");
while (token != NULL){
struct _node * newNode = createNode(token);
appendList(newList, newNode);
token = strtok(NULL, "\n");
}
return newList;
}
However, I get a bus error 10 when I use the second method.
You create a new node whenever you find \n or \0.
In your case your text ends immediately after the last \n and hence you create a node with 0 chacters.
Before calling createNode() you should simply check if you collected any characters since the last node was created.
Otherwise you will also get empty nodes if you have two \n without text in between.
The check could look like this:
else if (currChar == '\0') {
if (letterCount >= step+1)
{
struct _node * newNode = createNode(strlcpy(text,step,letterCount));
if(newList->head == NULL) {
newList->head = newNode;
}
else {
newList->last->next = newNode;
}
newList->last = newNode;
}
flag = 1;
}
Regarding your second approach:
How do you provide the text for your test? If it is a string literal, you cannot modify it and strtok() will fail. Apart from that I think strtok() is more suitable for your problem.

anagram detecting using linked lists in c

I'm trying to write a code that'll check 2 words if they are anagrams,using linked lists.To do that,I guess it should receive 2 words from the user and pass every letter they contain to linked list's nodes,and compare the nodes if they have the same letter,if so,remove the same letter from the second word.When the process is done,if the second list is empty,then they are anagrams.Even if 1 letter is not matching,it should return 0,but I don't know how to determine the length of these words,here is what I wrote so far
#include <stdio.h>
#include <stdlib.h>
struct node
{
struct node *prev;
struct node *next;
char data;
};
typedef struct node *NODE,NOD;
NODE last(NODE list)
{
if(list!=NULL)
while(list->next!=NULL)
list=list->next;
NODE lst;
lst=list;
return lst;
}
void insert( char letter, NODE list)
{
NODE nod;
nod=(NODE)malloc(sizeof(NOD));
nod->next=NULL;
nod->prev=NULL;
nod->data=letter;
if(list==NULL)
{
list=nod;
}
else
{
nod->prev=last(list);
last(list)->next=nod;
}
}
Just check that each word has the same number of each letter in it.
int anagrams(const char *a, const char *b) {
int counts[256] = {0};
while (*a) counts[*a++]++;
while (*b) counts[*b++]--;
for (int i = 0; i < 256; i++) {
if (counts[i]) return 0;
}
return 1;
}
Why use linked lists for such an easy problem?
O(N) solution:
Calculate frequencies of every letter for each word and then compare these 2 histograms. If they're equal, then one word can be obtained from another.
If you want to use your linked-list-based solution, then, the length of the word is, indeed:
Length of each input word (they must have the same length) - it can be calculated with a single traversal from the linked list head to the tail.
Amount of removed symbols
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
char data;
struct node *prev;
struct node *next;
} NODE;
NODE *newNode(char ch){
NODE *p = malloc(sizeof(NODE));
if(p){
p->data = ch;
p->prev = p->next = NULL;
}
return p;
}
void insert(NODE **list, NODE *node){
if(*list == NULL){
*list = node;
return ;
}
NODE *curr = *list;
while(curr){
if(curr->data >= node->data){//insert sort
if(curr->prev == NULL)
*list = node;
else
curr->prev->next = node;
node->prev = curr->prev;
curr->prev = node;
node->next = curr;
break;
}
if(curr->next == NULL){
curr->next = node;
node->prev = curr;
break;
} else
curr = curr->next;
}
}
NODE *input_word(){
NODE *word=NULL;
int ch;
while(EOF!=(ch=getchar()) && ch != '\n'){
insert(&word, newNode(ch));
}
return word;
}
bool isAnagram(NODE *word1, NODE *word2){
while(word1 && word2){
if(word1->data != word2-> data)
return false;
word1 = word1->next;
word2 = word2->next;
}
return word1 == NULL && word2 == NULL;
}
int main(){
NODE *word1, *word2;
printf("input word : ");
word1 = input_word();
printf("input other word : ");
word2 = input_word();
if(isAnagram(word1, word2))
printf("YES\n");
else
printf("NO\n");
//drop(word1);drop(word2);
return 0;
}

implementing a TRIE data structure

Hii ,
i Was implementing a trie in C ... but i am getting an error in the insert_trie function .
I could not figure out why the root node is not getting updated . Please help me with this.
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct
{
char value;
int level;
struct node *next;
struct node *list;
}node;
node *trie = NULL;
node *init_trie()
{
node *new = (node *)malloc(sizeof(node));
if(trie == NULL)
{
new->value = '$';
new->next = NULL;
new->list = NULL;
new->level = 0;
trie = new;
printf("\n Finished initializing the trie with the value %c",trie->value);
return trie;
}
printf("\n Trie is already initialized");
return trie;
}
node *insert_trie(char *s)
{
node *nodepointer = trie;
node *new = (node *)malloc(sizeof(node));
node *save = NULL;
int i=0;
while(s[i]!=NULL)
{
nodepointer = nodepointer->list;
while(nodepointer!=NULL)
{
if(s[i] == nodepointer->value)
{
printf("\n Found %c",nodepointer->value);
nodepointer = nodepointer->list;
i++;
}
save = nodepointer;
nodepointer = nodepointer->next;
}
new->value = s[i];
new->next = NULL;
new->list = NULL;
printf("\n Inserting %c",new->value);
save->next = new;
i++;
}
return trie;
}
int main()
{
int num;
char *s = (char *)malloc(sizeof(char)*10);
trie = init_trie();
printf("\n Enter the number of words to enter into the trie ");
scanf("%d",&num);
while(num>0)
{
scanf("%s",s);
//printf("%s",s);
trie = insert_trie(s);
printf("\n Finished inserting the word %s into the trie \n",s);
num --;
}
return 0;
}
I get a segmentation fault due to the line nodepointer = nodepointer->list in insert_trie function ... Why ????
P.S : This is not homework.But i am trying to implement it. I just could not find the mistake .
"Implement a trie with insert, search, and startsWith methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z."
I have written this very simple solution for the above question from LeetCode. It has passed all the 16 test cases from LeetCode. I hope this will help.
//node structure
struct TrieNode {
char value;
int count;
struct TrieNode * children[27];
};
static int count =0;
/** Initialize your data structure here. */
//return root pointer
struct TrieNode* trieCreate() {
struct TrieNode *pNode = NULL;
pNode = (struct TrieNode *)malloc(sizeof(struct TrieNode));
if (pNode)
{
pNode->value = '\0';
pNode->count =0;
memset(pNode->children, 0, sizeof(pNode->children));
}
return pNode;
}
/** Inserts a word into the trie. */
void insert(struct TrieNode* root, char* word) {
struct TrieNode *pCrawl = root;
count ++;
//check if the word is not empty
if(word){
int index=0, i =0;
//check if the root is not empty
if (root){
while( word[i] != '\0'){
index = ( (int) (word[i]) - (int)'a');
if(!pCrawl->children[index])
{
pCrawl->children[index] = trieCreate();
pCrawl->children[index]->value = word[i];
}
pCrawl = pCrawl->children[index];
i++;
}
//Count !=0 tell us that this is the last node;;
pCrawl->count = count;
}
}}
/** Returns if the word is in the trie. */
bool search(struct TrieNode * root, char* word) {
struct TrieNode *pCrawl = root;
bool flag = false;
//check if word is NULL
if(!word)
return false;
//if the trie is empty
if(!root)
{
return false;
}
//if word is empty
if (*word == '\0') {
return true;
}
int i=0, index =0 ;
while (word[i] != '\0')
{
index = ((int) (word[i]) - (int)'a');
//// if the node/character is not in Trie
if(!pCrawl->children[index])
{
flag = false;
break;
}
pCrawl = pCrawl->children[index];
i++;
}
//count != 0 marks node as last / leaf node
if(pCrawl->count != 0 && word[i] == '\0')
{
flag = true;
}
return flag;
}
/** Returns if there is any word in the trie
that starts with the given prefix. */
bool startsWith(struct TrieNode* root, char* prefix) {
struct TrieNode * pCrawl = root;
int i =0, index=0;
bool flag = false;
if(root){
while(prefix[i] != '\0')
{
index = ((int) (prefix[i]) - (int)'a');
if(pCrawl->children[index] == NULL){
flag = false;
return flag;
}
else
flag = true;
pCrawl = pCrawl->children[index];
i++;
}
}
return flag;
}
/** Deallocates memory previously allocated for the TrieNode. */
void trieFree(struct TrieNode* root) {
if(root){
for(int i = 0; i <=26; i ++)
{
trieFree(root->children[i]);
}
free(root);
}
}
// Your Trie object will be instantiated and called as such:
// struct TrieNode* node = trieCreate();
// insert(node, "somestring");
// search(node, "key");
// trieFree(node);
A trie holds one node per character and you're only performing one malloc per string. You should be calling malloc for every node. (Also, malloc.h is outdated. stdlib.h contains malloc since the ANSI C standard of 1989.)
node *insert_trie(char *s)
{
node *nodepointer = trie;
node *new = (node *)malloc(sizeof(node));
node *save = NULL;
int i=0;
while(s[i]!=NULL)
{
nodepointer = nodepointer->list;
while(nodepointer!=NULL)
{
if(s[i] == nodepointer->value)
{
printf("\n Found %c",nodepointer->value);
nodepointer = nodepointer->list; // Advance pointer once OK
i++;
}
save = nodepointer;
nodepointer = nodepointer->next; // Advance pointer without checking
}
new->value = s[i];
new->next = NULL;
new->list = NULL;
printf("\n Inserting %c",new->value);
save->next = new;
i++;
}
return trie;
}
Within the if test you advance nodepointer to nodepointer->list. Once the if test completes you advance nodepointer to nodepointer->next without checking if nodepointer is NULL from the advancement which occured within the if block.

Resources