Using a while loop to check the content of struct - c

I'm trying to append a node to a linked list however, when I use a while loop to check if the "link" is set to NULL, the loop is being executed when it shouldn't.
It is as if the "cursor->link" was not set to NULL and the code inside the while loop is being executed, I put the print statement there just to test it and it is being executed even though "cursor->link" is set to NULL. The create function returns a "node*".
EDIT - I apologize guys, I posted this question late at night and I guess I might not have been in the best shape to express myself properly. Plus I'm still a bit confused about how to handle and work with Linked Listing (as my code probably shows). I've been given a template to work with (as in the functions append and display were preset and I've to work with them as is). The compiler did not set off any warnings with the code as is. However the program still crashes in the append function around the While loop.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node {
int data;
struct node * link;
} node;
node* create(int data,node* link) {
node* newNode = (node*)malloc(sizeof(node));
newNode->data = data;
newNode->link = link;
return newNode;
}
void append ( node **, int ) ;
void display ( node * ) ;
int main() {
node *p ;
p=NULL;
int n;
char ch[10];
do {
printf("Enter the value\n");
scanf("%d",&n);
append(&p,n);
printf("Do you want to add another node? Type Yes/No\n");
scanf("%s",ch);
}while(!strcmp(ch,"Yes"));
printf("The elements in the linked list are");
display(p);
printf("\n");
return 0;
}
/* adds a node at the end of a linked list */
void append ( node **q, int num ){
node *cursor;
if (*q == NULL) {
*q = create(num, NULL);
node *cursor = *q;
}
while(cursor->link != NULL) {
printf("1\n");
cursor = cursor->link;
}
node* newNode = create(num, NULL);
cursor->link = newNode;
}
void display ( node *q ){
node *cursor = q;
while(cursor->link != NULL) {
printf(" %d", q->data);
cursor = cursor->link;
}
printf(" %d", cursor->data);
}

As Ry mentioned, problem is with the cursor you are using in while loop, it's never initialized. Instead you are creating a new variable with the same name when *q is null. I see one more problem in your code, when list is empty you are adding new node twice. First in null check condition and then after while loop.
To fix move this line
"node *cursor = *q"
outside if condition and add a return instead. Also remove this line
"node *cursor"
Note:: I am assuming your create method has no issue.

Related

Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000012)

I've tried to look up the solution to this problem through various other threads but my search was unsuccessful. I'm new to C and also new to this site so I apologize in advance if I'm incorrect in phrasing this question. I kinda have an idea of what's going on, but at the same time I might be entirely wrong. I have a linked list and I'm trying to insert at the end of the list. But when Xcode gets to the statement while(ptr->next!=NULL) it throws the error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000012)
I read somewhere before that it was because I'm accessing something that doesn't exist or I'm failing to initialize node->next to NULL but I did in the previous "if statement". I'm pretty new at coding with pointers and linked lists and again I apologize for any weird stuff that might be in my code ):
////LIST AND NODE STRUCTURES
//data nodes
typedef struct node{
int data;
int ID;
struct node* prev;
struct node* next;
} node;
typedef struct ListInfo{
int count; //numnodes
struct node *list; //list of nodes
} ListInfo;
////INSERT FUNCITON
void insert(ListInfo *H, node *n){
if(n == NULL)
return;
node* ptr = H->list;
if(H==NULL){
ptr = n;
ptr->next = NULL;
}
else{
while(ptr->next!=NULL){ //Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000012)
ptr = ptr->next;
}
ptr = n;
ptr->next = NULL;
}
// End of function
return;
}
////MAIN
int main(){ // No Edititng is needed for the main function.
ListInfo H;
H.count =0;
node *n;
int Data = 0,ID =0 ;
do{
printf("Enter an ID and a Value to add to the list, Enter -1 to stop: ");
//Get value from user to store in the new linked list node later.
scanf("%d %d",&ID,&Data);
// Check if the user entered "-1", if so exit the loop.
if(Data == -1||ID == -1)
return 0;
// Allocate memory for a new Node to be added to the Linked List.
n = malloc(sizeof(node));
// Put the Data from the user into the linked list node.
n->data = Data;
n->ID = ID;
//Increment the number of nodes in the list Header.
// If the current node count is zero, this means that this node is the first node
// in this list.
if(H.count++ == 0)
H.list = n;
// Otherwise, just use the insert function to add node to the list.
else insert(&H,n);
}while(Data != -1);
// Display all nodes in the list.
DisplayList(&H);
//Remove a node from the list, and display the list each time.
while(H.count != 0){
Delete(&H,H.list->data);
DisplayList(&H);
}
// Display the list, this should be empty if everything was correct.
DisplayList(&H);
}
When you allocate n you never set n->next. When you pass it to insert() you try to access the bad pointer and crash. When you set n->ID you should set n->next to NULL.

Sorted insert program in a linked list

I am a beginner in Data structures and I am learning linked list now .
I encountered a program about sorted insert where I had an add() function to add the nodes in the sorted order
/*Linked List program to add ascending order sorted nodes in
the list */
#include <stdio.h>
#include <stdlib.h>
enter code here
struct node {
int data ;
struct node link;
};
void add(struct node **q,int num){
struct node *r,*temp = *q;
r = malloc(sizeof(struct node )); //Data Allocated
r->data = num;
if(*q==NULL ||(*q)->data >num){
*q = r;
(*q)->link = temp;
}else{
while(temp !=NULL){
if(temp->data <=num &&(temp->link->data >num
||temp->link==NULL)){
r->link = temp->link;
temp->link=r;
return;
}
temp = temp->link;
}
}
}
void main(){
struct node *p;
p = NULL;
}
I have expected to add the nodes in sorted ascending order but when I input data then error is shown.I am Using Code Blocks to run the program in C
I think it has to do something with the end condition temp->link == null but I am unable to figure out exact condition for that part of code .Please Help !
The definition for the structure struct node is not correct. I assume it is a typo. It should be struct node *link;
Your conditions for traversing the loop are not correct. As mentioned in the comments, you are accessing temp->link in case it might be NULL.
You are not checking for the condition that the number to be added is greater than all the numbers and is to be added at the end of the list.
The modified function is below.
void add(struct node **q,int num){
struct node *r,*temp = *q;
r = malloc(sizeof(struct node )); //Data Allocated
r->data = num;
r->link = NULL;
if(*q==NULL ||(*q)->data >num){
*q = r;
(*q)->link = temp;
}else{
while(temp->link !=NULL){
if(temp->data <=num &&(temp->link->data >num)){
r->link = temp->link;
temp->link=r;
return;
}
temp = temp->link;
}
temp ->link = r; // add at the end as not added at any other location.
}
}
In addition to Rishikesh Raje's answer (you need to use a pointer inside struct: struct node* link;; you need to check first for link being null, then access link->data), the loop can be simplified quite a bit:
// advance only, if we need to insert (at least) after temp->link:
while(temp->link && temp->link->data <= num)
{
temp = temp->link;
}
// once the loop is done, temp points to the last element smaller than num, so:
r->link = temp->link;
temp->link = r;
Inside the while, we don't need to check for temp->data > num; we re-enter the loop only, if the loop condition was met previously, which checked exactly this condition already; remains the very first loop run; however, in this case, your if before the loop covered the condition already.
Side note: Is it a requirement to insert new elements after the existing ones? If not, inserting in front of is a bit faster, all you'd do is replacing <= with < and > with >=...
You should use
( temp->link == NULL || temp->link->data > num )
instead of
( temp->link->data > num || temp->link == NULL )
because if temp->link is NULL, the first code will return true immediately after checking the first condition and will not check the second condition, thus you will not get an error.
But when you use it like in the second expression, if temp->link is NULL, you will get an error because you are trying to reach a field named "data" of a NULL object with the code
temp->link->data

Can't seem to ever get the print function in linked list in c

cant print the linked list, it gets stuck in an infinite loop cant understand where i'm going wrong.
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
node *head = NULL;
void print(node *head){
node *temp = head;
while(temp!=NULL);
{
printf("%d => ",temp->data);
temp = temp->next;
}
printf("NULL");
}
node *clist(int n){
node *temp = NULL;
node *p = NULL;
int i;
for(i=0;i<n;i++)
{
temp = (node*)malloc(sizeof(node));
printf("Enter the elements of the list.\n");
scanf("%d",&temp->data);
}
if(head!=NULL)
{
while(p->next!=NULL)
p=p->next; //shifting p here node by node
p->next = temp; //last node which was just created
}
else
{
head = temp;
}
return head;
}
node *binsert(int x){
node *temp = NULL;
node *p = NULL;
temp = (node*)malloc(sizeof(node));
if(head!=NULL)
{
temp->next = head;
temp = head;
}
else
{
p = head = temp;
}
return head;
}
int main ()
{
int a, s, i, n,f;
printf("Choose an option : \n1.Create a list.\n2.Exit.\n");
scanf("%d",&s);
switch(s)
{
case 1:
printf("Very Well! Input the number of nodes\n");
scanf("%d",&n);
head = clist(n);
printf("Link List created successfully.\n");
print(head);
break;
default:
exit (0);
}
printf("Choose the operation you want to perform on the linked list:\n1.Add an element to the beginning.\n2.Add an element to the end.\n3.Add an element at a a particular position.\n");
scanf("%d",&a);
switch(a)
{
case 1:
printf("Enter the element you want to insert at the beginning.\n");
scanf("%d",&f);
binsert(f);
printf("Inserted Successfully.\n");
print(head);
break;
case 2:
printf("Error E162B");
}
return 0;
}
I tried changing the head to a global variable. re-wrote the code 7 times. please help.
First:
for(i=0;i<n;i++)
{
temp = (node*)malloc(sizeof(node));
printf("Enter the elements of the list.\n");
scanf("%d",&temp->data);
}
This loop repeats several times so that the user can enter the elements of the list. But it never adds any of the nodes to the linked list. Each iteration of the loop changes temp to point to a newly-allocated node but doesn't add the nodes to the linked list.
Second:
while(temp!=NULL);
This is an endless loop right here. If temp is not NULL, it's not changed anywhere in the loop, so it will never become NULL. You don't want that semicolon there.
Third:
node *head = NULL;
void print(node *head){
node *temp = head;
Don't do this to yourself. You have a global variable called head and you have a parameter called head. When you do node *temp = head; how obvious is it which head that's referring to. Don't give two variables the same name if their scope overlaps.
Fourth:
if(head!=NULL)
{
temp->next = head;
temp = head; // **** here
}
else
{
p = head = temp;
}
return head;
What's the point of temp = head;? The value of temp isn't accessed anywhere. So that can't be right.
Lastly:
I think you didn't ask the right question though. You asked us to explain where you're going wrong, and I've done that. But I don't think that's what you actually need. Maybe you need help developing the algorithm to solve the problem? Perhaps ask a new question describing what you think the algorithm should be (just in words, no need to use code) and ask for help fixing the algorithm.
And, to be blunt, the number of mistakes suggests that you are attempting a task that is significantly beyond your knowledge. This is frustrating and not a good way to learn programming. You should seriously consider attempting simpler tasks first.
You may have stripped it out to keep the question simple, but your real code should contain lots of extra checking and logging to help you understand it. Log when you enter a function. Log each decision the function makes. Log what functions return. That will help you determine where the program's actual operation is deviating from you think it should be doing. Or, if you prefer, learn to use your platform's debugging facilities. That way, you won't be making random changes and hoping that they make everything work but will instead know where the code is first going awry and be able to fix one thing at a time confident that you are not breaking things that were working.

deleting a node in linear single linked list given the start of the list

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.

Segmentation fault using doubly linked list in C

I've written an implementation of a doubly linked list with a .h prototype here and everything runs fine until I start entering values in the terminal. I get a segmentation fault after entering the second value, but, if I just use 1 value it executes normally. I've gone through it several times, but, I can't find my mistake. Could you guys help me find why I'm getting the error?
Here's the .h file:
#include <stdio.h>
typedef struct node Node;
struct node
{
int d;
Node *link;
}*head,*current,*prev;
int num_nodes;
void linked_list_init(int data);
void linked_list_sort();
void linked_list_print();
And here's the .c file:
#include "link.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
void main(){
int n,e,i;
printf("How many numbers do you want to sort: ");
scanf("%d",&e);
for(i=0;i<e;i++){
printf("Enter number: ");
scanf("%d",&n);
linked_list_init(n);
}
linked_list_sort();
printf("The sorted numbers are: ");
linked_list_print();
}
void linked_list_init(int data){
Node *prev=0,*next=0;
current=(Node*)malloc(sizeof(Node));
if(head==0)
{
head=current;
current->d=data;
current->link=0;
prev=current;
}
else{
current->d=data;
current->link=0;
prev->link=current;
prev=current;
}
}
void linked_list_sort(){
int i,j;
Node *prev=0,*next=0;
current=head;
prev=head;
next=head->link;
for(i=0;i<num_nodes-1;i++)
{
for(j=0;j<num_nodes-i-1;j++)
{
if(current->d>next->d)
{
current->link=next->link;
next->link=current;
if(current==head)
{
head=next;prev=next;
}
else
{
prev->link=next;prev=next;
}
if(next!=0) //check whether final node is reached
next=current->link;
}
else //move each node pointer by one position
{
prev=current;
current=next;
next=current->link;
}
}
//next iteration
current=head;
prev=head;
next=current->link;
}
}
void linked_list_print(){
current=head;
while(current!=0){
printf("%d ",current->d);
current=current->link;
}
}
The problem is that you're masking the global variables with local declarations in your function. That means that the variable prev in the functions are not the same as the global variable prev.
Aside from that, you should never place variable definitions in header files, as those will clash with each other if the header file is included in multiple files.
There is also another small bug, in that you don't increase the counter when inserting a new node into the list.
There is no need to initialize head to 0 because in your case you have declared it globally in header file ( although its not a good practice to declare variables in header files). The problem here is you are redefining prev node in void linked_list_init(int data) function. Just delete the prev node from there and everything would work fine.
Tips:
-> Declare the head, prev, current nodes in .c file.
-> Use NULL instead of 0 or even you can use (void *) 0 instead of simply 0
It seems like you are creating and initializing *prev and *current everytime the linked_list_init function is called. Hence after you enter the second value, the second if loop is using prev, which has actually been set to 0.
I think what you are trying to do is use the *prev, *head and *current as global variables (since you have declared them in your header file). Just use extern to declare them in the source file and things should work.
The global variable used in your program are uninitialized and hence prone to garbage values . Also i suggest the following defination for your node
struct node {
int d;
node *llink; // Left Link
node *rlink; // Right Link
};
typedef struct node* Node;
Node head = NULL; // Head node
Also
void linked_list_init(int data) {
Node newnode = (Node) malloc(sizeof (Node));
newnode->d = data;
Node curr;
if (head == NULL) {
newnode->llink = NULL;
newnode->rlink = NULL;
head = newnode;
} else {
curr = head;
while (curr->rlink) {
curr = curr->rlink;
}
curr->rlink = newnode;
newnode->rlink = NULL;
newnode->llink = curr;
}
}
The above will keep adding elements to the end of the list .
You can print data out easily as follows :
void linked_list_print() {
Node curr;
curr = head;
while (curr) {
printf("Element Data : %d", curr->d);
curr = curr->rlink;
}
}

Resources