Singly linked list in C(Inserting a node) - c

I have this problem when I input. The program will freeze and a pop out window will open and says " .exe has stopped working. "
It is just a simple insert and display fuction of a singly linked list. I tried everything. I rewrote the code and find another way of inserting. I tried different compiler.. It works on turbo C but I am using devC++.
Is this a compiler error?
Here is the code:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
#include <string.h>
typedef struct process
{
int pNum;
struct process *next;
}node;
node *create_node(node x)
{
node *temp;
temp=(node *)malloc(sizeof(node));
if(temp==NULL)
{
return 0;
}
else
{
temp->pNum=x.pNum;
temp->next=NULL;
}
return temp;
}
node *insert_node(node *head,node *last,node x)
{
node *temp;
temp=create_node(x);
if(head==NULL && head==last)
{
head=temp;
last=temp;
head->next=NULL;
last->next=NULL;
}
else
{
last->next=temp;
last=temp;
last->next=NULL;
}
return head;
}
int main()
{
node *head=NULL,*last=NULL,*temp,input;
int i,x,y,num;
printf("INPUT NUMBER: ");
scanf("%d",&num);
x=0;
y=6;
for(i=0;i<num;i++)
{
gotoxy(39,y);
scanf("%d",&input.pNum);
head=insert_node(head, last, input);
y++;
}
getch();
return 0;
}
I think I have found out what line it stopped working.
On the function insert_node
The line last->next=temp;
It seems I can't find what I had done wrong.

You need this:
node *insert_node(node *head, node **last, node x)
{
node *temp;
temp=create_node(x);
if(head==NULL && head== *last)
{
head=temp;
*last=temp;
head->next=NULL;
(*last)->next=NULL;
}
else
{
(*last)->next=temp;
(*last)=temp;
(*last)->next=NULL;
}
return head;
}
Call like this:
head=insert_node(head, &last, input);
Your function needs to modify the last pointer. In C values including pointers are passed by value. So if you modify the function argument inside the function, the argument passed to the function won't be modified. That is what happens in your program.
In the modified we don't pas simpty the lastpointer but we pass a pointer to the last pointer which will allow us to modify the last pointer of the main function.
Simple Example:
int func1(int x)
{
x = 10;
return 2;
}
int func2(int *x)
{
*x = 10;
return 2;
}
...
int x = 3;
printf ("%d\n", func1(x));
printf ("%d\n", x);
printf ("%d\n", func2(&x));
printf ("%d\n", x);
Will print:
2
3
2
10

In your code, after the first entry head pointer will point to new value. Because of you are assigning the return value of that calling function. But last value will not be affect. Because of your are calling that as a pass by value. At
next time head == last will be fail.
It will go to else block, and you are accessing the
last->next=temp;
It is like accessing the null pointer this is the reason. If you need to avoid this you need to call last as pass by reference.

Related

How to Reverse singly linked list properly in C? [duplicate]

This question already has answers here:
How to reverse a singly linked list using only two pointers?
(36 answers)
Closed 7 years ago.
well im starting with C and i've been asked to do a linked list that has random integers in its nodes data, they must be in ascendant order and later i have to reverse their order with a function. The problem im having is that in my reverse output, im only getting the first number and its not even reversed.
#include <stdio.h>
#include <stdlib.h>
int N;
typedef struct node{
int num;
struct node *next;
}nodes;
int first_node(nodes *head){
if(head == NULL){
printf("Error");
}
else{
head -> num= rand();
head->next=NULL;
}
}
int second_node(nodes *head){
nodes *uno=malloc(sizeof(nodes));
if(uno == NULL){
printf("Error");
}
else{
uno->num = rand();
uno->next = NULL;
if( uno->num>head->num){
head->next=uno;
}
else{
head= uno->next;
}
}
}
int insert_node(nodes *head){
nodes *dos=malloc(sizeof(nodes));
if(dos == NULL){
printf("Error");
}
else{
dos->num = rand();
dos->next = NULL;
nodes *current = head;
while(current!= NULL){
if(current->num<dos->num && current->next==NULL){
current->next = dos;
return;
}
else if (current->num<dos->num && current->next->num>dos->num){
dos->next=current->next;
current->next=dos;
return;
}
else if(head->num>dos->num){
dos->next=head;
head=dos;
}
current=current->next;
}
}}
void printnodes(nodes *head){
nodes *current = head;
while (current != NULL){
printf("%d\n",current->num);
current = current ->next;
}
}
void reverse(nodes *head)
{
nodes *a=head->next;
if(a!=NULL)
{
nodes *b=a->next;
a->next=head;
head->next=NULL;
head=a;
if(b!=NULL)
{
while(b!=NULL)
{
a=b;
b=b->next;
a->next=head;
head=a;
}
a->next=head;
head=a;
}
}
}
int main(){
printf("Insert the number of nodes u want to create:");
scanf("%d", &N );
nodes *head =malloc(sizeof(nodes));
int i =3;
if(N==1){
first_node(head);
}
else if (N ==2){
first_node(head);
second_node(head);
}
else if (N>2){
first_node(head);
second_node(head);
while(i<=N){
insert_node(head);
i++;
}
}
printnodes(head);
printf("\n\n Reversed \n\n");
reverse(head);
printnodes(head);
return 0;
}
The output im getting creating 5 nodes is :
In order:
41
3445
3890
8709
16777
Reversed :
41
how can i fix this?, thanks and sorry for the bad english
There are two very obvious problems in your code:
The first is that you assign to a local variable, expecting that assignment to be reflected once the function returns. I'm talking about your assignment to head in most functions. The problem here is that when you pass an argument to a function. it's passed by value, meaning it's copied and what you have in the function you call is just a copy or the original value. And as you should know, changing a copy will not change the original.
The second problem that I see at a quick glance is in the second_node function, where you first do
uno->next = NULL;
and potentially followed by
head= uno->next;
This will assign NULL to head.
The first problem is easy to solve, by emulating something called pass by reference. I say emulating, as C only have pass by value. You can emulate pass by reference in C using pointer, which means that to pass a pointer "by reference" in C, you have to pass a pointer to the pointer, like
int second_node(nodes **head){
...
}
You then call it using the address-of operator:
second_node(&head);
Then in second_node you use the dereference operator * to access the "original" head pointer, like
*head = uno->next;
Writing the above I noticed a third problem, and that is that you declare some functions as returning an int, but you don't actually return anything from the functions. Thankfully it seems that you don't use the returned value anywhere, but it's still is undefined behavior to not return a value in a function that should return a value. If you should not return a value from a function it must be declared as returning void:
void second_node(nodes **head){...}

segmentation error in ubuntu

Please tell me why the segmentation error is there in my program there is no error .
I also tried to debug it but it never goes inside the for statement.
#include<stdio.h>
#include<malloc.h>
struct node
{
int data;
struct node* link;
} *start;
main()
{
int i,n,m;
start=NULL;
printf("enter the number of nodes you want");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("enter the element you want to insert");
scanf("%d",&m);
create_list(m);
}
}
create_list(int data)
{
struct node *q,*temp;
temp=(struct node *)malloc(sizeof(struct node));
temp->data=data;
temp->link=NULL;
if(start==NULL)
start=temp;
else
{
while(q->link!=NULL) q=q->link;
q->link=temp;
}
}
You forgot to initialize q before using it:
q = start;
while(q->link!=NULL)
1.You haven't initialized q in create_list() and used it -
while(q->link!=NULL)
Intialize q=start; before this loop.
2.Also free the allocated memory for temp in function.
3.main() should be int main(void) and what is type of create_list? Declare its prototype before main.
In the function create_list local pointer q was not initialized
struct node *q,*temp;
^^^
However it is accessed in the loop
while(q->link!=NULL)
I think you mean the following
else
{
q = start;
while ( q->link != NULL ) q = q->link;
q->link = temp;
}
Take into account that the function should be declared before its usage. Place it declaration for example before main. And its return type shall be void and specified explicitly. Also function main shall have return type int.
For example
void create_list( int data );
int main( void )
{
//...
And it is a good idea to free all dynamically allocated memory before exiting the program.
Also header <malloc.h> is not a standard C header. You should use <stdlib.h> instead.
After all suggestions from the above it will be clearly in the future if you try to show some work of your clear codding and to respect the minimum standard.
Here is a way of how should be looking your code:
#include<stdio.h>
#include<stdlib.h> /* You need stdlib not malloc */
void create_list(int data); /* If you don't declare your function the compiler doesn't know nothing about create_list */
struct node{
int data;
struct node* link;
}*start;
int main(void){ /* Here return type of main is int and if no arg needed should be used void */
int i,n,m;
start=NULL;
printf("enter the number of nodes you want");
if((scanf("%d",&n)) != EOF) /* always check scanf's return */
for(i=0;i<n;i++){
printf("enter the element you want to insert");
if((scanf("%d",&m)) != EOF) /* here the same: always check scanf's return */
create_list(m);
}
return 0; /* return of main should be 0 or one of the following: EXIT_SUCCESS or EXIT_FAILURE, but 0 will be ok because it is standard*/
}
void create_list(int data){ /* here should be explicit what kind of function is */
struct node *q,*temp;
temp=(struct node *)malloc(sizeof(struct node)); /* if you allocate memory dynamically ..... */
temp->data=data;
temp->link=NULL;
if(start==NULL){
start=temp;
}else{
q = start;
while(q->link!=NULL){
q=q->link;
q->link=temp;
}
}
free(temp); /* .....then always free it */
}

Using a Binary Tree

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node_{
int val;
struct node_ *left;
struct node_ *right;
}node;
node* insert(node* root,int val);
void inorder(node* root);
int main(void)
{
int i;
int item;
node* root = NULL;
srand(time(NULL));
for( i = 0; i < 10; i++)
{
item = rand()%15;
insert(root,item);
}
inorder(root);
return 0;
}
node* insert(node* root,int val)
{
if(root == NULL)
{
root = malloc(sizeof(node));
if(root!= NULL)
{
(root)->val = val;
(root)->left = NULL;
(root)->right = NULL;
}
else
printf("%d not inserted. No memory available.\n",val);
}
else
{
if(val < (root)->val)
{
insert((root->left),val);
}
if(val>root->val)
{
insert(((root)->right),val);
}
}
}
void inorder(node* root)
{
printf("%p",root);
if(root != NULL)
{
inorder(root->left);
printf("%3d",root->val);
inorder(root->right);
}
}
I am trying to create a binary tree and print out the values in order. However when I run this code the printf of the address prints out nil obviously meaning that my tree is empty so the printf and recursion below does not run. I cannot figure out where I went wrong, any suggestions or answers would be appreciated because I can't figure out why the root would be null after calling all of those inserts in main.
You pass root as a parameter to insert() (which says it is going to return something but doesn't). Inside insert you malloc your node and assign it to the local variable root. Nothing you ever do makes it out of the insert function.
Try returning something from insert, or using a global root.
As #JoshuaByer hints in the comments below, another approach is to make your insert method "pass by reference" so it can effectively modify what was passed to it.
void insert(node** rootp,int val)
{
if(*rootp == NULL)
{
*rootp = malloc(sizeof(node));
}
/* and so on */
If you don't understand what this is saying, google "Pass by reference in C" and I'm positive you'll get some good information.
In main() after declaring and initializing root (node* root = NULL;) you're never assigning it. In order to fix you should probably change the lin insert(root,item); to root = insert(root,item);.
Also note that although insert is defined as returning node * it does not return any value.

Making of linked list by head and node

here's my code in C for making of linked list. Its giving runtime error after the while loop gets executed for one time. Plz help me in correcting my code. (totally confused that where's the error.) I am making a head node first and then adding child nodes to it.
#include <stdio.h>
#include <stdlib.h>
typedef struct node nd;
typedef nd *link;
struct node{
int data;
link next;
};
typedef struct {
int size;
link head;
}list;
void create(link temp)
{
link new;
new=(link)malloc(sizeof(nd));
printf("enter data: ");
scanf("%d",new->data);
temp->next=new;
temp=temp->next;
}
list createlist()
{
list sl;
sl.size=0;
sl.head=0;
return sl;
}
int main()
{
list sl;
sl=createlist();
link temp;
temp=sl.head;
char c;
while (1)
{
printf("Add node?: ");
scanf(" %c",&c);
if (c=='y')
{
create(temp);
sl.size++;
}
else
break;
}
return 0;
}
your createlist() function is returning a reference to a local variable that goes out of scope after it returns. You should instead return a heap based value:
list* createlist() {
list* sl = (list*)malloc(sizeof(list));
sl->size=0;
sl->head=0;
return sl;
}
Initially temp points to NULL. temp = sl.head;
In create(temp) temp->next = new;
You are dereferencing a NULL, address 0x0. I get a segmentation fault when I do that.
Need to change the algorithm.
A debugger shows this problem immediately.
You could use a pointer to pointer for temp. It would be easier to read if you didn't use a typedef for a pointer to node. I haven't tested this, but it should be close:
nd ** create(nd **temp)
{
nd *new;
new=(nd *)malloc(sizeof(nd)); /* this cast shouldn't be needed */
printf("enter data: ");
scanf("%d",&(new->data));
new->next = NULL;
*temp = new;
return &(new->next);
}
/* ... */
int main()
{
nd **temp;
temp = &(sl.head);
/* ... */
temp = create(temp);
/* ... */
}

Binary search tree insertion - root always null

I have ds code for inserting values in a binary search tree using recursion. The problem is that the root always remains null.
Upon execution, the 1st printf() prints 10 but the 2nd printf (after insertRec(10)) does not print anything as root is null.
#include<stdio.h>
#include<malloc.h>
struct llist
{
int data;
struct llist *left;
struct llist *right;
};
typedef struct llist node;
void insertRec(node *r, int num)
{
if(r==NULL)
{
r=(node*)malloc(sizeof(node));
r->data=num;
r->left=NULL;
r->right=NULL; printf("%d ",r->data); //1st printf
}
else
{
if(num < r->data)
insertRec(r->left, num);
else
insertRec(r->right, num);
}
}
void display(node *x)
{
if(x != NULL)
{
display(x->left);
printf("%d-->",x->data);
display(x->right);
}
else
return;
}
int main()
{
node *root=NULL;
insertRec(root,10);
if(root !=NULL)
printf("\ndata=%d",root->data); //2nd printf
insertRec(root,5);
insertRec(root,15);
insertRec(root,3);
insertRec(root,18);
display(root);
getch();
}
You are passing root as value so changes made to root in insert function doesn't reflect at main function, hence root remains NULL in main function. To rectify your code, you need to pass Pointer to pointer. Pass address of root to reflect change in main function.
void insertRec(node *r, int num)
should be coded like:
void insertRec(node **r, int num)
{
if(*r==NULL)
{
*r= malloc(sizeof(node));
(*r)->data=num;
//
and use *root inside insert function.
And call it as insertRec(&root, 10); from main.
Additionally, if you allocates memory dynamically then you should free allocated memory using free explicitly.
One more thing learn Indenting C Programs.

Resources