Why does the following code display a blank linked list? - c

Why does the following code display a blank linked list? I want to insert single characters to each node in the linked list. The characters are from the ch string. It works fine when I change the node member sc to integer and modify the associated code. But it seems there is an issue with using characters.
#include <stdio.h>
#include <string.h>
struct node {
char sc[1];
struct node *next;
};
char ch[30];
void insert(struct node **head_ref,int j) {
struct node *new_node = (struct node*)malloc(sizeof(struct node));
struct node *last = *head_ref;
new_node->sc[0] = ch[j];
new_node->next = NULL;
if (*head_ref == NULL) {
*head_ref=new_node;
return;
}
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
return;
}
void display(struct node *head) {
struct node *t = head;
while (t != NULL) {
printf("%s", t->sc);
t = t->next;
}
}
main() {
FILE *fp;
fp = fopen("C:\\Users\\Jefferson Warie\\Desktop\\input.txt", "r");
if (fp == NULL) {
printf("File could not be opened.");
}
struct node *num1h;
num1h = NULL;
int i = 0, j;
char arr[100][30];
char ch[30];
while (!feof(fp)) {
fgets(arr[i], 31, fp);
i++;
}
for (i = 0; i < 2; i++) {
strcpy(ch, arr[i]);
for (j = 0; ch[j] != '\0'; j++) {
if (i == 0) {
insert(&num1h, j);
}
}
}
printf("First linked list: ");
display(num1h);
}

You have declared character array ch twice — once as a global variable and once local to main.
Also, you need to add #include<stdlib.h> to use malloc
This is the final updated code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
char sc[1];
struct node *next;
};
char ch[30];
void insert(struct node **head_ref,int j) {
struct node *new_node=(struct node*)malloc(sizeof(struct node));
struct node *last=*head_ref;
new_node->sc[0]=ch[j];
new_node->next=NULL;
if (*head_ref==NULL) {
*head_ref=new_node;
return;
}
while(last->next!=NULL) {
last=last->next;
}
last->next=new_node;
return;
}
void display(struct node *head) {
struct node *t=head;
while(t!=NULL) {
printf("%s",t->sc);
t=t->next;
}
}
void main() {
FILE *fp;
fp=fopen("C:\\Users\\Jefferson Warie\\Desktop\\input.txt","r");
if(fp==NULL) {
printf("File could not be opened.");
}
struct node *num1h;
num1h=NULL;
int i=0,j;
char arr[100][30];
while(!feof(fp)) {
fgets(arr[i],31,fp);
i++;
}
for(i=0; i<2; i++) {
strcpy(ch,arr[i]);
for(j=0; ch[j]!='\0'; j++) {
if(i==0) {
insert(&num1h,j);
}
}
}
printf("First linked list: ");
display(num1h);
}

Related

I am trying to reverse a linked list using recursion in C, I have some doubts on my recursive function

Below is the program
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
struct node* reverse_ll(struct node* hnode)
{
if(hnode == 0)
{
return 0;
}
if(hnode->next == 0)
{
head=hnode;
return hnode;
}
struct node* ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next=0;
//return hnode;
}
void display()
{
struct node *ptr;
ptr=head;
if(ptr==0)
{
printf("empty");
}
else
{
while(ptr!=0)
{
printf("%d->",ptr->data);
ptr=ptr->next;
}
printf("null");
}
}
int main()
{
struct node* h;
lastinsert(1);
lastinsert(2);
lastinsert(3);
lastinsert(4);
lastinsert(5);
display();
h=reverse_ll(head);
display();
return 0;
}
In function reverse_ll() even if I comment "return hnode" I am getting the right output How is it possible where does ptr receives its address from when I comment "return hnode"?
output: 1->2->3->4->5->null
5->4->3->2->1->null
reverse_ll() must return a struct node * in the recursive case:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head;
void lastinsert(int data) {
struct node **c = &head;
for(; *c; c = &(*c)->next);
*c = malloc(sizeof(*head));
if (!(*c)) {
printf("malloc failed\n");
return;
}
(*c)->data = data;
(*c)->next = NULL;
}
struct node *reverse_ll(struct node* hnode) {
if(!hnode)
return NULL;
if(!hnode->next) {
head = hnode;
return hnode;
}
struct node *ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next = NULL;
return hnode;
}
void display() {
if(!head) {
printf("empty");
return;
}
for(struct node *ptr = head; ptr; ptr = ptr->next) {
printf("%d->",ptr->data);
}
printf("null\n");
}
int main() {
for(int i = 1; i <= 5; i++) {
lastinsert(i);
}
display();
reverse_ll(head);
display();
// It's good practice to implement a function that frees you list
// which you would call here.
return 0;
}
and example run:
$ ./a.out
1->2->3->4->5->null
5->4->3->2->1->null

Add element linked list

#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node ** head, int n);
void display_list(node * head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
printf("Insert size of list: ");
scanf("%d",&n);
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void create_list(node **head,int n){
node *new,*tmp;
int num,i;
*head = malloc(sizeof(node));
if(*head == NULL){
printf("Memory can not be allocated.");
}
else{
printf("Insert element 1: ");
scanf("%d",&num);
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for(i=2;i<=n;i++){
new = malloc(sizeof(node));
if(new == NULL){
printf("Memory can not be allocated.");
break;
}
else{
printf("Insert element %d: ",i);
scanf("%d",&num);
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
scanf("%d", &num);
new->data = num;
new->next = NULL;
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
}
}
I don't understand why after using the add_e() function, the display_list() function gives to me only the last two number of the list. The add_e() fucntion should be add an element at the end of the list. What am i doing wrong?
Edit: Added create_list() function so you can understand better but now it says to me to add more details so I'm writing something.
In main, n is unitialized, so you'll get random/bad results.
The add_e should not use *head in the while or even do a while. The printf says "insert at beginning", which is different/simpler. This is what I've currently coded up/fixed.
You'd want to use a loop, if you [really] wanted to insert/append to the end of the list. But, the loop would still be incorrect, because you don't want to advance head when finding the end.
I've also fixed the printf for prompts and scanf
Here's a refactored/fixed version of your code with the bugs annotated:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
// NOTE/BUG: n is unitialized
#if 1
n = 5;
#endif
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void
create_list(node **head, int n)
{
node *new,
*tmp;
int num,
i;
*head = malloc(sizeof(node));
if (*head == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element 1: ");
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for (i = 2; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
else {
printf("Insert element %d: ", i);
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
fflush(stdout);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
#if 0
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
#else
if (*head == NULL)
*head = new;
else {
new->next = *head;
*head = new;
}
#endif
}
}
UPDATE:
In add_e, because I couldn't be sure if you wanted to insert at beginning of list [based on the printf] or at the end [based on the code], I created a version that is cleaned up a bit more and demonstrates both types:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_begin(node **head);
void add_end(node **head);
int
main(void)
{
int n;
node *head;
setbuf(stdout,NULL);
head = NULL;
printf("Enter initial number of list elements: ");
scanf(" %d",&n);
create_list(&head, n);
display_list(head);
add_begin(&head);
display_list(head);
add_end(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
node *cur;
if (head == NULL) {
printf("Empty list.\n");
}
for (cur = head; cur != NULL; cur = cur->next)
printf("DATA: %d\n", cur->data);
}
void
create_list(node **head, int n)
{
node *new, *tmp;
int num, i;
tmp = *head;
for (i = 1; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
printf("Insert element %d: ", i);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
if (*head == NULL)
*head = new;
else
tmp->next = new;
tmp = new;
}
}
// add_begin -- insert at before head of list
void
add_begin(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Insert element at the beginning: ");
scanf(" %d", &num);
new->data = num;
new->next = *head;
*head = new;
}
// add_end -- add to tail/end of list
void
add_end(node **head)
{
node *new;
node *tmp;
node *tail;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Append element at the end: ");
scanf(" %d", &num);
new->data = num;
new->next = NULL;
// find the tail
tail = NULL;
for (tmp = *head; tmp != NULL; tmp = tmp->next)
tail = tmp;
if (tail != NULL)
tail->next = new;
else
*head = new;
}

How to delete nodes in a doubly linked list

I'm having trouble deleting nodes in a doubly linked list, the program crash and i can't figure out the problem. Can you please help me?
This is the full code that creates new nodes, views them and deletes them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
void Delete(Node * head, Node del)
{
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test;
Node list = NULL;
Node del = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: printf("\nElement to Delete: ");
scanf("%d", &del->structure.id);
Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
I think the problem is related to the scanf() for the Node del, but i'm not sure. When i just pass list or list->next as second argument to the function Delete() it works. Is everything all right with the code?
int main()
{
...
Node del = NULL;
...
scanf("%d", &del->structure.id);
Your program should crash here. You are dereferencing a null pointer.
Probably you will need to read the user input into a temporary id variable, then search the list for a matching item, and if you find one, then you can try deleting it.
Ok, i added a function that searches for the node to be deleted and i modified a bit the Delete() function, this is the workaround, thank you for the suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->structure.id == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head, struct Test temp)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test, del;
Node list = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
del value is NULL, but you reference it when you delete.
What you need is to search a node in the list for the givent id and then delete it.

segmenation fault error in my linkedList -C

I put together a few pieces of code to make a linked list that adds to head(Has a special function) and in the middle(also special function).
my problem is, i need to provide the program with numbers and insert them as nodes in my LINKEDLIST. However, my display function(to display the tree of nodes) gives back segmentation fault and so does just taking values in without any display function.
I'm fairly new to malloc so i suspect the problem is there?
Thanks
#include<stdio.h>
#include<stdlib.h>
/*LINKEDLIST STRUCT*/
struct node {
int data;
struct node *next;
};
/*Inserting head-Node*/
struct node *insert_head(struct node *head, int number)
{
struct node *temp;
temp = malloc(sizeof(struct node));
if(temp == NULL)
{
printf("Not enough memory\n");
exit(1);
}
temp->data = number;
temp->next = head;
head = temp;
return head;
}
/*Inserting inside a list*/
void after_me(struct node *me, int number)
{
struct node *temp;
temp = malloc(sizeof(struct node));
if(temp == NULL)
{
printf("Not enough memory\n");
exit(1);
}
temp->data = number;
temp->next = me->next;
me->next = temp;
}
/*PRINTING LIST*/
void display(struct node *head)
{
struct node *moving_ptr = head;
while(moving_ptr != NULL)
{
printf("%d-->",moving_ptr->data);
moving_ptr = moving_ptr->next;
}
}
int main()
{
int index;
struct node *head;
struct node *previous_node;
scanf("%d", &index);
while(index > 0)
{
/*allocating in List */
if(head == NULL)
head = insert_head(head,index);
else
if((head != NULL) && (index <= (head->data)))
{
struct node *temp;
head->next = temp;
temp->next = head;/*TRY INSERT HEAD FUNC.*/
}
else
if((head != NULL) && (index > (head->data)))
{
previous_node->data = index-1;
after_me(previous_node,index);
}
scanf("%d", &index);
}
display(head);
}
I suggest as follows.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
//aggregated into one place
struct node *new_node(int number){
struct node *temp;
if(NULL == (temp = malloc(sizeof(*temp)))){
printf("\nNot enough memory\n");
exit(1);
}
temp->data = number;
temp->next = NULL;
return temp;
}
struct node *insert_head(struct node *head, int number) {
struct node *temp = new_node(number);
temp->next = head;
return temp;
}
void after_me(struct node *me, int number){
struct node *temp = new_node(number);
temp->next = me->next;
me->next = temp;
}
void display(struct node *head){
struct node *moving_ptr = head;
while(moving_ptr != NULL){
printf("%d", moving_ptr->data);
if(moving_ptr = moving_ptr->next)
printf("-->");
}
putchar('\n');
}
struct node *insert(struct node *me, int number){
if(me){
if(number <= me->data){
me = insert_head(me, number);
} else {
me->next = insert(me->next, number);
}
} else {
me = new_node(number);
}
return me;
}
void release(struct node *list){//Of course, you will be able to replace a simple loop(e.g while-loop).
if(list){
release(list->next);
free(list);
}
}
int main(void){
struct node *head = NULL;
int index;
while(1==scanf("%d", &index) && index > 0){
head = insert(head, index);
}
display(head);
release(head);
return 0;
}

Segmentation fault error in BST

I keep getting a segmentation fault error when I call the find_word function in my main.
when a word is added I want to return 1 and when it finds that word, I want it to return 1.
So I'm also not sure if my insert method is correct either.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct node {
char *word;
struct node *left;
struct node *right;
};
static struct node *root;
int init(void)
{
struct node *new_node = malloc (sizeof(struct node));
if(new_node==NULL){
return 0;
}
else{
root = new_node;
new_node->left = NULL;
new_node->right = NULL;
return 1;
}
}
static int insert(struct node *newnode, char *word)
{
struct node *temp = NULL;
if(!(newnode))
{
temp = (struct node *)malloc(sizeof(struct node));
temp->left =NULL;
temp->right = NULL;
temp->word = word;
newnode = temp;
return 0;
}
if(word < (newnode)->word)
{
insert((newnode)->left, word);
}
else if(word > (newnode)->word)
{
insert((newnode)->right, word);
}
return 1;
}
int add_word(char *word)
{
return insert(root,word);
}
static int find(char *word, struct node *newnode){
if(newnode==NULL){
return 0;
}
else if(strcmp(word,newnode->word)>0){
find(word,newnode->left);
}
else if(strcmp(newnode->word,word)<0){
find(word,newnode->right);
}
else{
return 1;
}
return 0;
}
int find_word(char *word)
{
return find(word,root);
}
int main(int argc,char *argv[])
{
int k;
char l[5];
k = init();
printf("init: %d\n",k);
strcpy(l,"x");
k = add_word(l);
printf("add_word(%s): %d\n",l,k);
strcpy(l,"x");
k = find_word(l);
printf("find_word(%s): %d\n",l,k);
return 0;
}
to fix like this
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct node {
char *word;
struct node *left;
struct node *right;
};
static struct node *root = NULL;
static int insert(struct node **newnode, char *word){
struct node *temp = NULL;
int cmp;
if(!*newnode){
temp = (struct node *)malloc(sizeof(struct node));
temp->left =NULL;
temp->right = NULL;
temp->word = strdup(word);
*newnode = temp;
return 0;
}
if((cmp=strcmp(word, (*newnode)->word)) < 0)
return insert(&(*newnode)->left, word);
if(cmp > 0)
return insert(&(*newnode)->right, word);
return 1;
}
int add_word(char *word){
return insert(&root, word);
}
static int find(char *word, struct node *newnode){
int cmp;
if(newnode==NULL)
return 0;
if((cmp=strcmp(word, newnode->word)) == 0)
return 1;
if(cmp < 0)
return find(word, newnode->left);
return find(word, newnode->right);
}
int find_word(char *word){
return find(word, root);
}
int main(int argc,char *argv[]){
int k;
char *w;
k = add_word(w="x");
printf("add_word(%s): %d\n", w, k);
k = find_word(w);
printf("find_word(%s): %d\n", w, k);
return 0;
}
If newnode->word is NULL, you should insert the word at the current node, to handle the empty root node.
static int insert(struct node *newnode, char *word)
{
struct node *temp = NULL;
if(!(newnode))
{
temp = (struct node *)malloc(sizeof(struct node));
temp->left =NULL;
temp->right = NULL;
temp->word = malloc(strlen(word)+1);
strcpy(temp->word, word);
newnode = temp;
return 0;
}
if (newnode->word == NULL) {
newnode->word = malloc(strlen(word)+1);
strcpy(newnode->word, word);
return 1;
}
if(strcmp(word,(newnode)->word) < 0)
{
insert((newnode)->left, word);
}
else if(strcmp(word,(newnode)->word) > 0)
{
insert((newnode)->right, word);
}
return 1;
}
In your find function, you call strcmp twice. You swap the order of the arguments, but you also change > 0 to < 0. These cancel each other out, so both are testing the same thing. You need to change one or the other, but not both. You should also check for newnode->word == NULL.
static int find(char *word, struct node *newnode){
if(newnode==NULL || newnode->word == NULL){
return 0;
}
else if(strcmp(word,newnode->word)>0){
find(word,newnode->left);
}
else if(strcmp(word,newnode->word)<0){
find(word,newnode->right);
}
else{
return 1;
}
return 0;
}

Resources