I am implementing Singly Linked List on my program. Now I have this display function to display what is inside my singly linked list. Now the problem is when I call my display function. It only prints the head. For example 20-->NULL. Display function for checking if I implement Singly linked list correctly.
struct node
{
int data;
struct node *next;
}*start=NULL;
void display()
{
struct node *new_node;
printf("The Linked List : ");
new_node=start;
while(new_node!=NULL)
{
printf("%d--->",new_node->data);
new_node=new_node->next;
}
printf("NULL");
}
void creat(int num)
{
struct node *new_node,*current;
new_node=malloc(sizeof(struct node));
new_node->data=num;
new_node->next=NULL;
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
//printf("%d->",new_node->data);
}
void main()
{
int binrange,max=100,n,i,divi;
int inp[4];
clrscr();
printf("enter 5 numbers: ");
for(i=0;i<5;i++)
{
scanf("%d",&inp[i]);
}
printf("\nenter range: ");
scanf("%d",&binrange);
n=max/binrange;
divi=max/n;
for(i=0;i<=max;i++)
{
if(i%divi==0 && i>0)
{
//create nodes here
//store i into nodes
creat(i);
}
}
display();
getch();
}
The variable current is a local variable inside the creat function, and it goes out of scope (and "disappears") every time the creat function exits.
That means two things: The variable will always be uninitialized everytime you call the function, and by dereferencing the (uninitialized) pointer you have undefined behavior.
The reason for the undefined behavior is just because the variable is uninitialized. Uninitialized non-static local variables have an indeterminate value, and in reality if will be seemingly random. So what you are doing is taking this pointer that points to a "random" location and write to it.
There are three possible solutions: One is to make the current variable static, the other is to make it global, and the third is to not have it at all and find the end every time the function is called. Oh, and if you go for one of the two first, you should probably rename it to end (or something similar) because that's what it is, a pointer to the end of the list.
In your code, you're defining
int inp[4];
and then you're reading
for(i=0;i<5;i++)
{
scanf("%d",&inp[i]);
}
Clearly past the allocated memory when i is 4 [array indexing in c starts from 0]. So, undefined behaviour.
EDIT:
Also, as Mr. Joachim Pileborg mentioned, struct node * current is local to the creat() function, as goes out-of-scope each and every time the function is finished.
Side Effects:
Every time you start with a fresh current having garbage [you did not initialize].
You'll be dereferencing uninitialized memory.
You need a way to store the value. Otherwise, again, UB.
P.S - Both the cases cause UB in their own ways. :-)
Related
I tried to do insertion in linked list by passing it to a function using pointer to pointer call(call by reference). I tried using a different variable for head pointer within the function, but insertion doesn't takes place due to use of that variable at some places (as mentioned in the code below). If i use *head in place of hd at the below mentioned position the code runs successfully.
Why this problem arises?
**EXPLAINED MY PROBLEM AND QUESTION IN THE CODE BELOW**
typedef struct ll {
int data;
struct ll *next;
}list;
**insert(&head,&n); this is used in main() for insertion**
**FUNCTION FOR INSERTION IN LINKED LIST**
void insert(list **head,int *n) **n=size of linked list**
{
list *hd;
hd=*head; **i am trying to use this variable for convenience**
int pos,i,value;
list *ins,*t;
printf("\nenter position to insert ");
scanf("%d",&pos);
if(pos>(*n+1) || pos<1)
{
printf("\ninvalid position\n");
return;
}
printf("enter value to insert ");
scanf("%d",&value);
ins=(list*) malloc(sizeof(list));
ins->data=value;
if(pos==1)
{
ins->next=hd; **hd can be used here**
*head=ins; ***this is the problem postion***
**if i use hd=ins here then no insertion takes place,why?**
**but if i use *head=ins as used then code runs successfully.**
}
else
{
for(i=1;i<pos-1;i++) **BUT IN THIS BLOCK ALSO ,I CAN USE hd i.e. not neccessary to use *head **
{
hd=(hd->next);
}
t=hd;
hd=(hd->next);
t->next=ins;
ins->next=hd;
}
*n=*n+1;
}
I think, your "list" in "insert" is exist in "insert" only and drops after exiting from it. It needed or copy the added structure in already existing sequence and correct the pointers or provide empty place in the array with sequence or ti increase this array before inserting and in any case correct pointers. And I prefer two-relation list.
the compiler stops working ,pls give me some solution
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
node * create()
{
node *p;
p=malloc(sizeof(node));
p->next=NULL;
return p;
}
void add(node **h,int ele)
{ node *temp;
temp=(*h);
node *p=create();
while(temp->next!=temp)
temp=temp->next;
temp->next=p;
p->next=temp;
p->data=ele;
(*h)=temp;
}
void main()
{ int ch,ele;
node *h;
h->next=h;
do
{ printf("\n1 add 2 delete 3 insert at kth position 4 delete at kth position");
scanf("%d",&ch);
if(ch==1)
{
scanf("%d",&ele);
add(&h,ele);
}
//if(ch==2)
}while(ch!=5);
}
Like I said in my comment, my guess is that you have a crash, that the program stops when you run the program, and that it builds without errors.
The reason is that you are using the local non-static variable h without initializing it. All local non-static variables have an indeterminate value unless initialized, and using those variable without initialization leads to undefined behavior.
The solution is very simple: Allocate memory for a node (either as a normal variable or dynamically) and initialize the pointer h with that.
Most compilers are actually capable of detecting problems of this kind, but since it's syntactically and semantically legal it will not issue an error, but a warning instead. And if you don't get such a warning then you need to enable more warnings.
I created a Singly Linked List and wrote a method to print it. It has compiled properly and ran,but at the end of execution, it shows list.exe(file generated after compilation of code) has stopped working and windows is checking for solution as shown below.
list.c
#include<stdio.h>
#include<stdlib.h>
struct List
{
int a;
List *b;
};
void PrintElement(List *);
int main()
{
List *head,*temp;
int n,k;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
temp->b=(List*)malloc(sizeof(List));
if(i==0)
{
temp=(List*)malloc(sizeof(List));
head=temp;
}
else
{
temp=temp->b;
}
scanf("%d",&temp->a);
}
temp->b='\0';
PrintElement(head);
return(0);
}
void PrintElement(List *head)
{
List *temp1=head;
do
{
printf("%d\n",temp1->a);
temp1=temp1->b;
}
while(temp1!='\0');
free(temp1);
}
Can anybody explain what i am doing wrong?
You have undefined behavior, because of this line
temp->b=(List*)malloc(sizeof(List));
At this point you haven't initialized temp yet, you do it a couple of lines down.
You also never initialize the "next" pointer b to NULL anywhere, so when you traverse the list you will go outside of the list leading once again to undefined behavior. And to add insult to injury, you then attempt to free the node that you got by walking beyond the end of the list. As well as only freeing that memory, and not the actual nodes you allocate.
Also, there is a distinct different between the null-character that marks the end of strings, and a null-pointer. Most compilers will evaluate both '\0' and NULL to the same actual value, but they are still distinct semantic entities.
I've been trying to learn C by myself after basic Java knowledge and I'm trying to implement a linked list. I'm running into trouble when making a createList function - a function that's supposed to make an empty list. I'm having a bit of a weird problem with passing pointers though. These are just snippets of the code, and my definitions of the node / list are located in a header file given by a book CD (so that's not the problem)
LList* createList(void){
LList list;
list.first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:%d\n",list.first,&list);
return &list;
} //This prints 0 and then the address of list
void print_list(LList *list){
printf("\nList from print_List\nFirst%d\nAddress:%d\n", list->first,list);
} //This prints some random non-null address for some reason, but also the
//SAME address as the list from createList. Why does list->first not print as 0?
int main(void)
{
LList*newList = createList();
printf("\nList from main:\nFirst:%d\nAddress:%d\n", newList->first,newList);
print_list(newList);
system("pause");
return 0;
} //Prints same exact thing as the printf in the createList.
return &list;
list resides on stack and its lifetime completes as function returns. So, using a pointer to it invokes undefined behavior.
Create the object on heap.
Here is your problem:
LList* createList(void)
{
LList list;
...
return &list;
}
Variable list is allocated on the stack, whenever you enter the code of function createList.
Whenever this function (or any other function for that matter) is called, the stack is in a different status.
Sometimes it's 75% full, sometimes only 24% (this is just a figure of speech though).
Your local variable is allocated at the next free slot in the stack, so it doesn't have a constant address throughout the lifetime of your program, but only during the execution of the function itself.
Shorty after the function returns, some other local variable might be allocated in the same address.
Hence, there is no point in returning this address, as you are doing in your code.
UPDATE:
One optional solution for you is to declare LList newList in main, and pass &newList to createList instead of returning a value from that function:
void createList(LList* list)
{
list->first = NULL;
printf("List from mk_list: \nfirst:%d\nlist address:0x%X\n",list->first,list);
}
P.S.: You should probably name this function initList instead.
I wrote the following function which returns the middle element of a linked list, which uses the double pointer method
struct node
{
int data;
struct node *next;
}*start;
void middleelement()
{
struct node *x=start,*y=start;
int n=0;
if(start==NULL)
{
printf("\nThere are no elments in the list");
}
else
{
while((x->next)!=NULL)
{
x=x->next->next;
y=y->next;
n++;
}
printf("\nMiddle element is %d",y->data);
}
}
However, whenever I run the functions, the Windows explorer stops working
What is the flaw in the code?
Is there any better algorithm than this to find the middle element?
If the number of entries is odd, your x will end up being NULL, so when the next loop iteration dreferences it, your program is going to crash. You should modify your condition to account for that:
while(x && x->next) {
...
}
Comparing with NULL is optional in C, so you can skip the != NULL to shorten the condition.
Of course passing the start parameter through a global variable is unorthodox, to say the least. It would be much better to pass it as a regular function parameter.