When I run the following code, it gives me an infinite looping result. However if I comment out the free pointer lines in the insert function i.e. free(ptr) and free(ptrnext) then it works fine. Can anybody explain why is it so?
I am pretty sure that the print and takeInput works fine, and hence can be ignored.
#include<stdio.h>
#include<stdlib.h>
typedef struct Nodes{
struct Nodes * next;
int val;
}Node;
//Function to create a linked list
Node * takeInput(){
int data;
Node *start =NULL ;
Node *tail=NULL;
printf("Enter the number of nodes");
int num,i;
scanf("%d",&num);
for(i=1;i<=num;i++){
if(start==NULL){
start=malloc(sizeof(Node));
puts("Enter data");
scanf("%d",&data);
start->val=data;
start->next=NULL;
tail=start;
}
else{
Node * ptr = malloc(sizeof(Node));
puts("Enter data" );
scanf("%d",&data);
ptr->val=data;
tail->next=ptr;
tail=tail->next;
}
}
tail->next=NULL;
return start;
}
//Function to print
void print(Node * head){
Node*ptr=head;
while(ptr!=NULL){
printf("%d->",ptr->val);
ptr=ptr->next;
}
}
//Function to insert a node in given linked list
Node * insert(Node *start){
int i,data;
puts("Enter pos");
scanf("%d",&i);
puts("Enter data");
scanf("%d",&data);
Node * ptr=malloc(sizeof(Node));
ptr->val=data;
ptr->next=NULL;
if(i==1){
ptr->next=start;
start=ptr;
free(ptr);
}
else{
Node * ptrnext=start;
while(i!=1){
ptrnext=ptrnext->next;
i--;
}
ptr->next=ptrnext->next;
ptrnext->next=ptr;
free(ptr);
free(ptrnext);
}
return start;
}
int main(void){
Node * start =takeInput();
start=insert(start);
print(start);
}
When I run the following code, it gives me an infinite looping result. However if I comment out the free pointer lines in the insert function i.e. free(ptr) and free(ptrnext) then it works fine.
This is undefined behavior. (when you don't comment the free() functions)
Once you've freed memory you must remember not to use it any more.
Note : the pointer might or might not point the same block after freeing, it's undefined behavior
so don't free the pointer unless you want to destroy or delete the node.
so don't use the free() in the insert function as you are not deleting any node.
Apart from that, I don't see any function to deallocate the memory at the end of the program.
Always make sure to deallocate the allocated memory at the end using a delete() function.
Here's a typical implementation of delete function
void delete(Node* start)
{
Node* temporary = NULL;
while(start != NULL)
{
temporary = start->next; //saving next node address
free(start); //freeing current node
start = temporary; //assigning start with next node address
}
printf("successfully destroyed the list!"); //function exit message
}
Call it at the end of main() function or when you wish to delete the entire list
Related
This is a program to print two link lists using one function.
I have used two functions i.e create and display.Create() is to create the linklist and display() to display the result of linklist.
But this code is printing NULL. I'm not not getting where is the error???
`#include<stdio.h>
#include<conio.h>
struct node
{
int data;
struct node* next;
}
*start=NULL,*start1=NULL;
//to create the linklist
struct node* create(struct node* ptr)
{ int ch;
do
{
struct node* new_node=(struct node*)malloc(sizeof(struct node));
struct node* current;
printf("enter the data\n");
scanf("%d",&new_node->data);
new_node->next=NULL;
if(ptr==NULL)
{
ptr=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("Do u want to add more ");
scanf("%d",&ch);
}while(ch!=0);
return ptr;
}
//to display the linklist
void display(struct node* temp)
{
while(temp!=NULL)
{
printf("%d--->",temp->data);
temp=temp->next;
}
printf("NULL\n");
}
int main()
{
clrscr();
create(start);
display(start);
printf("\n 2nd linklist\n");
create(start1);
display(start1);
getch();
return 0;
}
First problem
current must be declared outside the do/while loop, otherwise you will get undefined behaviour because there is no guarantee that current will keep it'svalue from one iteration to the next. However with certain compilers you may get away with it.
Second problem
Calling create(start); will not modify start because variables in C are passed by value. You need to write start = create(start);. See also this SO question. In your program start is still NULL after the call to the create function. You could have found out that easily by yourself.
I am unable to append a new node in the linked list. I have already identified the problem area but after much research and trying many things I am still unable to resolve the issue.
The problem is with the for loop in insert_node(char,struct **) function and traverse(struct *) function both of which never seem to terminate:
// program that stores name of the user using linkedlist
#include<stdio.h>
#include<stdlib.h>
typedef struct LIST{
int flag;
char name;
struct LIST *next;
} LISTNODE;
LISTNODE *head=NULL,*newnode=NULL;// global pointers
LISTNODE* initialize(); //initializes struct node with default values and returns a node
void insertNode(char c,LISTNODE** temp);
void traverselist(LISTNODE *temp);
int main(){
char ans,ch;
printf("\n\nEnter your name and hit enter-\n\n");
do{
printf("your name:");
fflush(stdin);
scanf("%c",&ch);
insertNode(ch,&head);
printf("\n\ninsertnode-back to main()");
printf("Want to continue?(Y?N):");
fflush(stdin);
scanf("%c",&ans);
}while(ans=='y'||ans=='Y');
printf("\n\ntraverselist-leaving main()");
traverselist(head);
printf("\n\ntraverselist-back to main()");
return 0;
}
void insertNode(char c, LISTNODE **temp){
printf("\n\ninto insertnode: before initialize");
LISTNODE* temp2;
newnode=initialize();
printf("\n\nback to insertnode:after initialize");
//printf("\nnewnode->name=%c",newnode->name);
//printf("\nnewnode->flag=%d",newnode->flag);
newnode->name=c;
//printf("\nnewnode->name=%c",newnode->name);
//printf("\nnewnode->flag=%d",newnode->flag);
//for(;(*temp)!=NULL;temp=&(*temp)->next);
/*while((*temp)->next!=NULL){
temp=&(*temp)->next;
printf("\n\nIn while!");
}
*/
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!") ;
//printf("\n\nout of while!");
(*temp)=newnode;
}
LISTNODE* initialize(){
static int count=0;
LISTNODE *tempnewnode;
printf("\n\nINto inintialize!");
tempnewnode=(LISTNODE*)malloc(sizeof(LISTNODE));
if(tempnewnode==NULL){
printf("No memory available. Aborting!");
exit(0);
}
else{
tempnewnode->flag=0;
tempnewnode->name='*';
tempnewnode->next=NULL;
if(count==0){
head=tempnewnode;
count++;
}
}
return tempnewnode;
}
void traverselist(LISTNODE *temp){
printf("\n");
for(;temp!=NULL;temp=temp->next){
printf("%c",temp->name);
}
}
Please help!
The problem is inside the insert_node function, specifically with the loop:
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!");
You'd be better advised not to use the reference temp in your loop, as it overwrites the head->next back to itself. Create another temporary pointer.
I changed the insertNode(char, LISTNODE**) to the following:
void insertNode(char c, LISTNODE *temp){
LISTNODE** temp2=&temp;
newnode=initialize();
printf("\n\nback to insertnode:after initialize");
newnode->name=c;
for(;(*temp2)!=NULL;temp2=&(*temp2)->next)
printf("\n\nIn for!") ;
(*temp2)=newnode;
}
and function is called like this:
insertNode(ch,head);
It works just fine!
The problem is this portion of your insertNode function
for(;*temp!=NULL;temp=&((*temp)->next))
printf("\n\nIn for!") ;
//printf("\n\nout of while!");
(*temp)=newnode;
Here you should first check if the link list is empty or not if it is empty then you can create the new node and assign the address of it to temp.
If not then depending upon whether you want to insert the new element in the end, beginning or middle of the list you should traverse the list then perform the insertion.
For example if you want to perform insertion at the beginning then after creating the new node you should assign the address of the start pointer of the list to the next of newly created node and move the start to the new node as you have to keep track of the start pointer.
I have the following code which deletes a given node from the linear single linked list.
I want to know if we can still improve this program and does it break anytime
struct node
{
int num;
struct node *next;
} ;
typedef struct node s;
void delete(struct node *first)
{
int flag = 0;
s *ptr, *lastNodePtr = NULL, *deleteNode;
deleteNode = (s*) malloc(sizeof(s));
printf("enter the node value to delete");
scanf_s("%d",&deleteNode->num);
deleteNode->next = NULL;
for (ptr=first;ptr!=NULL;ptr=ptr->next) //at least one element exist
{
if(deleteNode->num == ptr->num)
{
flag=1;
if(ptr==first) //need to delete at first place
{
free(ptr);
first = null; //i dont think we need to do this as it points to ptr and ptr is already null.
}
else // need to delete some where middle.it can be last as well.
{
lastNodePtr->next=ptr->next;
free(ptr);
}
printf("successfully deleted..");
break;
}
lastNodePtr=ptr; // taking note of last node visited..
}
if (flag==0)
{
printf("\n Couldn't find the node");
return;
}
}
if ptr is the first element in the list to delete, you set first to null, not to the next of ptr. (sideeffect: you are not able to free the the rest of the list)
your EDITH: delete should return the new Head, better make it a struct node **first parameter which changes the first element if the first is the deleted one
BTW: never cast the result of malloc.
BTW two. why use for-loop? everybody uses while-loop with linked lists
BTW three: normal variable names for linked lists are "head", "list", "next", "prev", "last" with the nice side-affect, they are all the same length, so making it neatly aligned.
struct node
{
struct node *next;
int num;
} ;
void delete(struct node **pp, int num) {
struct node *del;
for ( ;*pp; pp= &(*pp)->next) {
if((*pp)->num == num) break;
}
if (!*pp) { printf("Couldn't find the node(%d)\n", num); return; }
del = *pp;
*pp = del->next;
free(del);
}
BTW: there is nothing wrong with for() loops; they allow you to put all the loop logic on one line.
I am working on a simple text editor in C. I am having troubles with inserting an element in a linked list.
Here is my structure:
struct node {
struct node *previous;
int c;
int x;
int y;
struct node *next;
}*head;
Here is my insertion code:
void checker(int ch, int xpos, int ypos)
{
int flag=0;
struct node *temp,*temp1,*insert_node=NULL;
temp=(struct node *)malloc(sizeof(struct node));
temp=head;
while(temp!=NULL)
{
if(temp->x==xpos && temp->y==ypos)
{
insert_node->c=ch;
insert_node->x=xpos;
insert_node->y=ypos;
if(temp->previous==NULL) //this is for inserting at the first
{
insert_node->next=temp;
head=insert_node;
}
else //this is for inserting in the middle.
{
temp1=temp;
temp=insert_node;
insert_node->next=temp1;
}
flag=1;
break;
}
temp=temp->next;
}
//this one's for the normal insertion and the end of the linked list.
if(flag==0)
characters(ch,xpos,ypos);
}
None of the inserting in the first and middle works. I do not know where it went wrong. Please help me.
temp=(struct node *)malloc(sizeof(struct node));
temp=head;
You are allocating space for a new node, but then you loose the address of this new node assigning temp=head.
The problem is that insert_node is a local variable in your function checker() which is also initialized as NULL. Doing insert_node->c means NULL->c which i'm sure you'll agree with me that is wrong.
Try to dynamically allocate memory for your variables before using them and you should be fine.
insert_node will always be NULL in the code you posted.
Also, you may want to split your code more; start by isolating part of it in a find() function.
I am trying to implement a stack with linked lists. I am having problems with the pop() function. It compiles OK, but when I try to run the code it crashes on tmp=tmp->head; and I have no idea why. I tried google but didn't find the answer. Here is the full code:
struct node{ //kreiram stog
struct node* head;
struct node* next;
int broj;
}node;
void push_onto(int broj){ // dodajem na glavu
struct node* novi;
novi=(struct node*)malloc(sizeof(struct node));
//novi=novi->head;
if (novi== NULL)
printf("Smth is wrong,Jose!\n");
else
novi->broj=broj;
novi->next=novi->head;
novi->head=novi;
}
int pop()// skidam sa stoga
{
struct node* temp;
temp=temp->head;
int br;
if (temp->next==NULL)
return -1;
else
br=temp->head;
temp=temp->next;
free(temp);
return br;
}
void top(){ //koji je element na stogu
struct node* tmp;
printf("Trenutni element na stogu je %d",tmp->broj);
}
void is_empty(){
struct node* tmp;
tmp=tmp->head;
if (tmp->head ==NULL)
printf("List is empty!\n");
}
void print_elem(){
struct node* tmp;
tmp=tmp->head;
if (tmp->head==NULL)
printf("Smth gone wrong!\n");
while (tmp!=NULL)
{
printf("Number is: %d",tmp->broj);
tmp=tmp->next;
}
printf("\n");
}
int main(void){
push_onto(15);
push_onto(10);
push_onto(20);
push_onto(12);
//print_elem();
printf("The element removed is : %d",pop());
//print_elem();
return 0;
}
This is not my homework, although it looks as such. This is just my attempt at trying to figure out some basic algorithms.
Thanks in advance! :)
struct node* temp;
temp=temp->head;
You never allocated anything for temp. It's just an uninitialized pointer.
It's not clear what you are trying to pop. Your pop() function takes no parameters and it accesses no globals. Likewise, I see the same problem with most of your functions there. They are supposed to operate on some sort of stack object, but none of them actually take such an object as a parameter.
I think you're close to "getting it". I remember it was a bit hard for me to understand structs and pointers at the beginning. But once you "get it" you'll be fine.
It seems you're trying to construct a stack using a simply-linked list. I'll try to offer some suggestions.
The very first thing that I would modify is your node struct. It is true, you need to keep
track of the head node, but usually you don't need to do it on every node. So we will remove it from your node definition.
struct node{ //kreiram stog
struct node* next;
int broj;
};
Now, you need to keep track of the head node of your list. This can be done with a global variable, that I'm going to call head:
struct node* head = NULL;
I'm initializing it to null because it is empty. A null head pointer will always mean
your stack is empty. All the code that tries to manipulate the list WILL need to start
with this head node. It is your anchor point.
Then to the push_onto() function
void push_onto(int broj){ // dodajem na glavu
// this bit is fine
struct node* novi;
novi=(struct node*)malloc(sizeof(struct node));
if (novi== NULL)
printf("Smth is wrong,Jose!\n");
else { //I'm adding the bracket, you require it to enclose more than one statement
//in the else section
novi->broj = broj; // store the number to be pushed on the stack
novi->next = head; // link the list, remember head will
// be NULL if the stack was empty
head = novi; // make the new node the current head node
}
}
Let's modify the pop() function
int pop()// skidam sa stoga
{
struct node* temp;
int result;
// first we will check if the head node is NULL (stack is empty)
if( head == NULL ) {
printf("Stack is empty\n");
return -1;
} else {
// hold a temporary value to current head pointer, so we can modify the head node
// and still refer to it
temp = head;
// Head node should now point to the next node on the list (will become NULL when
// popping the last value. This is what actually "pops" the value from our list
head = head->next;
// place in temporary variable the result we are popping. This is so because
// it's not a good idea to reference the node after we free the memory it is using
result = temp->broj;
// release the memory occupied by the node we're popping
free(temp);
return result;
}
}
Finally I'm going to show you how to fix some of the functions that are using your stack
void top(){ //koji je element na stogu
if( head == NULL ) {
printf("Stack is empty\n");
} else {
printf("Trenutni element na stogu je %d",head->broj);
}
}
void print_elem(){
struct node* tmp;
// As you can see, we're initializing tmp to head, since head will always point
// to the top element of your stack.
tmp = head;
if (tmp==NULL) {
printf("Stack is empty!\n");
return;
}
while (tmp!=NULL)
{
printf("Number is: %d",tmp->broj);
tmp=tmp->next;
}
printf("\n");
}
Hope things are clearer now. The head node is kept apart as a global variable and as I said before, it is the anchor point to begin manipulating the list. Feel free to ask me if you're still confused.
=)