LinkedList with unwanted zeros - c

Ive looked around and I'm not sure if it has been posted or not, but I am trying to create two linked lists in C. When they are supposed to be 'empty' there are zeros. I am not sure where these zeros are coming from and its confusing the hell out of me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int price;
int bookNumber;
struct node * next;
};
void addNode(struct node* pHead, int pPrice, int pBookNumber);
void displayList(struct node* pHead);
void removeNode(struct node* pHead, int pBookNumber);
int main()
{
struct node* head1;
head1 = (struct node*)malloc(sizeof(struct node));
head1 -> next = NULL;
addNode(head1, 10, 1234);
addNode(head1, 35, 9876);
displayList(head1);
printf("\n");
struct node* head2;
head2 = (struct node*)malloc(sizeof(struct node));
head2 -> next = NULL;
// addNode(head2,13, 8888);
displayList(head2);
}
void addNode(struct node* pHead, int pPrice, int pBookNumber)
{
struct node* newNode;
struct node* ptr;
newNode = (struct node*)malloc(sizeof(struct node));
newNode -> price = pPrice;
newNode -> bookNumber = pBookNumber;
newNode -> next = NULL;
ptr = pHead;
if(pHead -> next == NULL)
{
pHead -> next = newNode;
newNode -> next = NULL;
}
else
{
while((ptr -> next != NULL))
{
ptr = ptr -> next;
}
ptr -> next = newNode;
newNode -> next = NULL;
}
}
void removeNode(struct node* pHead,int pBookNumber)
{
struct node *current, *prev;
current = pHead;
/*searching list for the desired data*/
while((current -> bookNumber != pBookNumber))
{
prev = current;
current = current -> next;
}
/*fixing links between nodes*/
prev -> next = current -> next;
/*freeing memory*/
free(current);
/*removing from end of list*/
if((current -> next = NULL))
{
prev -> next = NULL;
/*freeing memory*/
free(current);
}
}
void displayList(struct node* pHead)
{
while(pHead != NULL)
{
printf("$%d, book# %d -> ", pHead -> price, pHead -> bookNumber);
pHead = pHead -> next;
}
printf("NULL");
}
I added two entries to the first list and didn't add anything to the second list...Here is the output:
$0, book# 0 -> $10, book# 1234 -> $35, book# 9876 -> NULL
$0, book# 0 -> NULL
Process returned 0 (0x0) execution time : 0.001 s
Press ENTER to continue.

the first noticeable problem is that you appear to have a dummy node
in the beginning of the list
struct node* head1;
head1 = (struct node*)malloc(sizeof(struct node));
head1 -> next = NULL;
but you start printing from head not from head->next
ie including dummy node.

head1 and head2 are uninitialized nodes which you allocate in main. You then add two nodes to head1 and none to head2. You then print the lists from head1 and head2. So they start by printing those uninitialized nodes.

You are starting your print loop from the head, and at the very beginning you allocate the memory for your head1 node. This causes it to print the price and number of the node with unassigned price and book number.
This can be solved by passing a pointer to a pointer (struct node **pHead) into your addNode function and adding a check if the head node is NULL.
newNode -> next = NULL;
ptr = pHead;
if(pHead -> next == NULL)
{
pHead -> next = newNode;
newNode -> next = NULL;
}
else
{
while((ptr -> next != NULL))
{
ptr = ptr -> next;
}
ptr -> next = newNode;
newNode -> next = NULL;
}
This code has another issue here. You are setting the next pointer of newNode to NULL at the start, and then again prior to exiting out of your if-else. This is not necessary, because you are always going to the very end of the list.
free(current);
/*removing from end of list*/
if((current -> next = NULL))
{
prev -> next = NULL;
/*freeing memory*/
free(current);
}
This code has an issue of freeing the current node, and then I assume you are attempting to check if you are at the very end of the list. However, you are using an assignment operator here. Use == for comparison, and were you to attempt removal of nodes, this would cause a segmentation fault, because you are trying to access the memory you had just freed.
Another thing worthy of mention here is that the current->next will be NULL in fact, if this is the end of the list, so this check is not even necessary and thus can be removed all together.

Related

Segmentation fault in linked list with mutex

I am trying to create thread which insert data in linked list with mutex, but just getting segmentation fault. I have to set many thread with various data and just in the process of experiment with one data(like '10') and one thread.
typedef struct NODE{
int data;
struct NODE* next;
pthread_mutex_t lock;
}node;
node* head;
void* list1(void* args){
node *prev, *new_node;
pthread_mutex_lock(&new_node->lock);
new_node = (node*) malloc(sizeof(node*));
new_node -> data = 10;
new_node -> next = NULL;
if(head -> next == NULL){
head = new_node;
}else{
prev = head;
pthread_mutex_lock(&prev->lock);
while(prev -> next != NULL){
prev = prev -> next;
}
prev -> next = new_node;
pthread_mutex_unlock(&prev->lock);
pthread_mutex_unlock(&new_node->lock);
}
pthread_mutex_destroy(&prev -> lock);
pthread_mutex_destroy(&new_node -> lock);
}
int main(void){
void *thread_result;
int status, cnt;
pthread_t thread_id[1];
head -> next = NULL;
printf("%d\n", 1);
status = pthread_create(&thread_id[0], NULL, list1, NULL);
pthread_join(thread_id[0], &thread_result);
node* curr = head -> next;
while(curr -> next != NULL){
printf("%d\n", curr -> data);
curr = curr -> next;
free(curr);
}
return 0;
}
free() is required by dynamic allocation, so entered in main() function, but terminal says i'm getting segmentation fault.
What is my mistake? And how to identify problem efficiently? i'd appreciate your help.
If head is NULL then head -> next will give you a segmentation fault.
Replace head -> next = NULL (in main) and head -> next == NULL (in list1) with head = NULL and head == NULL respectively.

Appending a new node to linked list

Basically what title says, Im trying to append (add to end of my list). my BuildList function takes in a size parameter that determines how many nodes the list will have. my problem is with my append function. So if I have 5 as my head, how do I fix my append function so that random numbers will be added after 5?
typedef struct Node
{
int value;
struct Node* next;
} Node;
Node *createNode( int num )
{
Node *ptr;
ptr = (Node *) malloc( sizeof( Node ) );
ptr->value = num;
ptr->next = NULL;
return ptr;
}
Node* append (Node* head, Node* newNode)
{
if (head == NULL)
return newNode;
while (head -> next != NULL);
head -> next = newNode;
return head;
}
Node* buildList (int size)
{
Node* newNode = (Node*) malloc (sizeof(Node));
Node* head = NULL;
for (int i = 0; i < size; i++)
{
Node* newNode = createNode (rand () % 10);
head = append (head, newNode);
}
return head;
}
Well, the most glaring issue is this
while (head -> next != NULL);
I believe you meant to write something like this
Node *tmp = head;
while (tmp -> next != NULL) {
tmp = tmp->next;
}
tmp->next = newNode;
You don't want to modify head here since you return it later in the function. If you didn't use tmp, head would always point to the penultimate node in the list.
You just need to modify your while, why do you have an empty instruction there? If the head is not NULL then you will never exit:
while (head -> next != NULL)
{
head = head -> next;
}

Linked list troubles list not linking to head pointer

I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.

Memory Leaks in pop() for A Queue

My pop function does not seem to work as it should. Basically, my queue has a pointer to the first and last elements.
My pop functions starts by freeing the first element and assigning it to NULL.
Then it uses the pointer curr to get to the next element each time until it find a NULL.
Finally, my the first pointer in my queue gets assigned to prev, which was pointing to the last element before my curr reached null.
#include <stdlib.h>
struct Queue {
struct Node* first;
struct Node* last;
};
struct Node {
Item val;
struct Node* next;
};
void initQueue (struct Queue **queue){
(*queue) = malloc(sizeof(struct Queue));
(*queue)->first = NULL;
(*queue)->last = NULL;
}
struct Node* createNewNode(){
struct Node *newNode;
newNode = malloc(sizeof(struct Node));
newNode->next = NULL;
return newNode;
}
void push (Item val, struct Queue *queue){
struct Node* newNode = createNewNode();
newNode->val = val;
if(queue->first == NULL){
queue->first = newNode;
queue->last = newNode;
}
else{
newNode->next = queue->last;
queue->last = newNode;
}
}
void pop(struct Queue *queue){
struct Node* curr = queue->last;
struct Node* prev = queue->last;
free(queue->first);
queue->first = NULL;
while(curr != NULL){
prev = curr;
curr = curr->next;
}
queue->first = prev;
}
To pop from the front of the list, simply have first point to first->next.
void pop(struct Queue *queue)
{
if (NULL != queue->first) {
struct Node *first = queue->first;
// Update first ptr
queue->first = queue->first->next;
free(first);
// Only need to update tail if list is empty
if (NULL == queue->first) {
queue->last = NULL;
}
}
}
EDIT
Based on your comment it looks like you aren't seeing what I'm doing, so here's an example.
Assume the queue looks like this:
queue->first
↓
A → B → C → D ← queue->last
First, make a temporary pointer and have it point to queue->first. Then move queue->first so that it points to queue->first->next. The list now looks like:
queue->first
↓
A → B → C → D ← queue->last
↑
first (temp var)
Then, delete the temp var and the list is:
queue->first
↓
B → C → D ← queue->last
EDIT 2 I also notice your push function is incorrect. In a queue, you add new items to the end of the list and take items from the front (FIFO - First In First Out). Like people lining up to see a show. The first person to get there and get in line will be the first to enter the theater. And the last person to arrive goes to the back of the line. So push should be:
void push (Item val, struct Queue *queue){
struct Node* newNode = createNewNode();
newNode->val = val;
if(queue->first == NULL) {
queue->first = newNode;
queue->last = newNode;
}
else{
queue->last->next = newNode; // Add to END of list
queue->last = newNode;
}
}

I am creating a garbage node at the end of linked list just to specify NULL. How can I modify my code to prevent that?

#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
Node* temp = head;
if(head -> next == NULL){
head ->val = val;
head -> next = newNode;
}
else{
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}
As I said in the question, I'm creating a useless node at the end just to specify NULL. How can I remove that feature? I know I'm doing something wrong in the add_at_end function but I'm not able to rectify it. Help would be appreciated. Thanks
EDIT:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
typedef struct List{
Node* head;
} List;
void add_at_end(List* l, int val){
Node* newNode = malloc(sizeof(Node));
newNode -> next = NULL;
newNode -> val = val;
Node* temp = l->head;
if(temp == NULL){
l->head = newNode;
}
else{
while(temp->next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
}
}
void display(List* l){
Node* t = l -> head;
while(1){
printf("%d\n", t->val);
if(t->next == NULL) break;
t = t->next;
}
}
int main(){
List l;
l.head = NULL;
add_at_end(&l, 10);
add_at_end(&l, 20);
add_at_end(&l, 30);
display(&l);
return 0;
}
This is my final code.
I need help adding nodes to the middle of the list. How can I do that?
Your node usage is all confused. When you create a new node the value should be stored into that node and the node linked into the list. Instead what you are doing is trying to add the value into the last node and then linking in a dummy node. It's a bit convoluted so I'm not sure I've explained what you have done clearly. Here is what add_to_end should be more like:
add_to_end (Node** head, int val)
{
Node* temp;
Node* newNode = malloc(sizeof(Node));
if (!newNode) {
/* Error */
}
newNode->val = val;
newNode->next = NULL;
if (!*head) {
/* empty list. Just make new node the head */
*head = newNode;
} else {
/* Find the end of the list */
temp = *head;
while (temp->next) {
temp = temp->next;
}
/* temp is now the last node. Chain new node after it */
temp->next = newNode;
}
}
Instead of a null node, you can represent the end of the list with a value of NULL, i.e. with a null pointer. The list is empty when head is NULL and the last node has node->next == NULL.
For this to work, you must be able to update the head when you add a node, because after inserting the frst node, the head will no longer be NULL. (The same goes for inserting at the front or deleting the first node.)
This chan be achieved by passing a pointer to a node pointer:
void add_at_end(Node **head, int val)
{
Node* newNode = malloc(sizeof *newNode);
newNode->next = NULL;
newNode->val = val;
while (*head) {
head = &(*head)->next;
}
*head = newNode;
}
Then you call add_at_and like this:
Node *head = NULL;
add_at_end(&head, 1);
add_at_end(&head, 2);
add_at_end(&head, 3);
It is important that head is initialised to NULL. More generally, all your pointers should either be NULL or point to valid nodes.
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
} Node;
void add_at_end(Node* head, int val){
Node* newNode = (Node *)malloc(sizeof(Node));
newNode -> next = NULL;
if(head == NULL)
{
head = new_node;
head->val = val;
}
if(head -> next == NULL)
{
new_node ->val = val;
head -> next = newNode;
}
else{
Node *temp = head;
while(temp -> next != NULL){
temp = temp -> next;
}
temp -> next = newNode;
temp -> val = val;
}
}
void display(Node* l){
while(l->next != NULL){
printf("%d -->", l->val);
l = l->next;
}
printf("End\n");
}

Resources