Issues with C linked list - c

I have a function to insert a struct into a queue implemented as a linked list.
I am passing an array element as the process.
void q_insert (queue *q, process p) {
printf("before insert attemp\n");
if (q->head == NULL) {
q->head = malloc(sizeof(struct Node));
q->head->process = &p;
q->head->next = NULL;
q->tail = q->head;
printf("After insertion into empty\n");
}
else {
struct Node* temp;
temp = malloc(sizeof(struct Node));
temp->process = &p;
temp->next = NULL;
q->tail->next = temp;
q->tail = temp;
printf("after insertion into non empty\n");
}
}
When I call this function the first time on an empty list, it seems to work fine. When I try to insert a second item it adds the second entry, but it also replaces the first entry with a copy of the second. These are the structs used:
typedef struct {
char name[80];
int arrival_time;
int execution_time;
int priority; // high number is high priority
} process;
struct Node{
process* process;
struct Node* next;
} q_node;
typedef struct {
struct Node* head;
struct Node* tail;
} queue;

C only supports pass by value and when you pass the address of variable through pointer, the copy of the address that variable passes,and in your insert function When q == NULL, you're allocating memory and assigning that memory to q, but this won't change q outside your function: only the copy of q inside your function will be changed.
In order to change what the argument q points to, and have those changes reflected outside your function, you'll need to pass a pointer to a pointer like this:
void q_insert (struct node **q, process p) {
if (q->head == NULL) {
struct node* new_head = (struct node*)malloc(sizeof(struct node));
new_head->head->next = NULL;
.
.
*q=new_head;
.
.
}

Related

I'm having a problem creating a linked list [duplicate]

This question already has answers here:
Linked lists - single or double pointer to the head
(3 answers)
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 10 months ago.
#include<stdio.h>
#include<stdlib.h>
void insert_front(struct node* head, int block_number);
void insert_rear(struct node* head, int block_number);
void print_list(struct node* head);
struct node {
int block_number;
struct node* next;
};
int main(void)
{
struct node* list = NULL;
insert_front(list, 10);
insert_rear(list, 20);
insert_front(list, 30);
insert_rear(list, 40);
print_list(list);
return 0;
}
void insert_front(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
void insert_rear(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL) {
head = p;
}
else {
struct node* q = head;
while (q->next != NULL) {
q = q->next;
}
q->next = p;
}
}
void print_list(struct node* head)
{
struct node* p = head;
while (p != NULL) {
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
When I ran it, there was no result at all.
Now, in the insert_front function p->block_number = block_number, a message appears saying that the NULL pointer 'p' is being dereferenced... (The same thing appears in the insert_rear function.)
Could it be that I am declaring the pointer wrong?
Both insert_front and insert_rear need to convey possibly head modification back to the caller, and the caller needs to reap that information. Both should be declared to return struct node *, do so, and the code in main react accordingly. E.g.:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
struct node * insert_front(struct node *head, int block_number);
struct node * insert_rear(struct node *head, int block_number);
void print_list(struct node *head);
struct node
{
int block_number;
struct node *next;
};
int main(void)
{
struct node *list = NULL;
list = insert_front(list, 10);
list = insert_rear(list, 20);
list = insert_front(list, 30);
list = insert_rear(list, 40);
print_list(list);
return 0;
}
struct node *insert_front(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
struct node *insert_rear(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
struct node *q = head;
while (q->next != NULL)
{
q = q->next;
}
q->next = p;
}
return head;
}
void print_list(struct node *head)
{
struct node *p = head;
while (p != NULL)
{
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
Output
--> 30 --> 10 --> 20 --> 40
I leave the memory leaks for you to resolve.
In C all variables are passed by value – if you pass a pointer, then it is copied, too (not the pointed to object, of course...), and function parameters, apart from being initialised from outside, are nothing more than local variables. Thus via head = p; you just assign the local copy of the outside pointer, not the latter itself!
To fix that you have two options:
Return the new head and make the user responsible for re-assigning the returned value to his own head pointer.
Accept the head as pointer to pointer.
With second approach a user cannot forget to re-assign the (potentially) new head, so that's what I'd go with:
void insert_whichEver(node** head, int block_number)
{
// use `*head` where you had `head` before...
}
void demo()
{
node* head = NULL;
insert_front(&head, 1012);
}
And in insert_front drop return head;, a function with void cannot return anything concrete and does not require a return at all (but bare return; can be used to exit a function prematurely).

Node pointer to current Node during mutile function call

I have declared a global pointer ptr and want that it should point to current node during different function call.
This is a sample code where I am creating a new node in fun1 and inserting in link list. In func2 I want to update the other members of newNode in linklist with a different value.
Currently I am traversing the link list to get the current Node or last Node which I dont want since during insertion of new Records already we have to traverse to reach to last Node thus storing the address of last Node.
But by doing the below I am not getting the proper values. Kindly someone suggest where I went wrong.
I am doing like this :
#include<stdio.h>
#include <stdlib.h>
struct Node
{
int data1;
int data2;
struct Node* next;
};
struct Node* head=NULL;
struct Node* ptr =NULL; /* Global pointer */
void insertNode(struct Node ** , struct Node* );
void fun1();
void fun2();
void fun1()
{
struct Node* ptr1 =NULL;
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
ptr1->data1=1; /* intilaizing with some values */
insertNode(&head,ptr1);
}
void fun2()
{
/* Updating the current Node in the linklist with new value . */
ptr->data2=2;
}
void insertNode(struct Node ** head, struct Node* NewRec)
{
if(*head ==NULL )
{
NewRec->next = *head;
*head = NewRec;
ptr=*head;
}
else
{
/* Locate the node before the point of insertion */
struct Node* current=NULL;
current = *head;
while (current->next!=NULL )
{
current = current->next;
}
NewRec->next = current->next;
current->next = NewRec;
ptr=current->next;
}
}
int main ()
{
fun1();
fun2();
while(head!=NULL)
{
printf("%d", head->data1);
printf("%d",head->data2);
head=head->next;
}
return 0;
}
You made a classic mistake.
This is wrong:
ptr1 = (struct Node*)malloc(sizeof(struct Node*));
The allocated space here is sizeof(struct Node*) which is the size of a pointer (usually 4 or 8 bytes depending on the platform). But you need to allocate space for the whole struct Node structure, whose size is sizeof(struct Node).
So you simply need this:
ptr1 = (struct Node*)malloc(sizeof(struct Node));
BTW: in C you don't cast the return value of malloc so you actually should write this:
ptr1 = malloc(sizeof(struct Node));

** pointer and * pointer in C [duplicate]

This question already has answers here:
Modifying head pointer in a linked list
(4 answers)
Closed 9 years ago.
I'm trying out a simple program on linked list add in between and beginning.
#include<stdio.h>
#include<malloc.h>
struct node{
int data;
struct node* link;
};
/* Count the no of items in the list */
int count(struct node* q){
int c = 0;
while(q != NULL){
q = q->link;
c++;
}
return c;
}
/* Add a list at the last */
void append(struct node **q,int num){
struct node *temp,*r;
temp = *q;
/* List is empty */
if(temp == NULL){
temp = malloc(sizeof(struct node));
temp->data = num;
temp->link = NULL;
*q = temp;
}
else{
/* go to the last node */
while(temp->link != NULL){
temp = temp->link;
}
/* add node at the end */
r = malloc(sizeof(struct node));
r->data = num;
r->link = NULL;
temp->link = r;
}
}
/* add a node after the specific node */
void addafter(struct node *q,int loc,int num){
struct node *temp,*r;
int i;
temp = q;
/* Skip to the desired portion */
for(i = 0; i < loc; i++){
temp = temp->link;
if(temp == NULL){
printf("\n Few nodes - less nodes %d elements in list \n",loc);
return;
}
}
/* insert new node */
r = malloc(sizeof(struct node));
r->data = num;
r->link = temp->link;
temp->link = r;
}
/* add a node at the beginning */
void addatbeg(struct node **q, int num){
struct node *temp;
/* add a new node */
temp = malloc(sizeof(struct node));
temp->data = num;
temp->link = *q;
*q = temp;
}
/* Delete a linked list */
void delete(struct node **q,int num){
struct node *temp,*old;
temp = *q;
while(temp != NULL){
if(temp->data == num){
/* Node to be deleted is the first node */
if(temp == *q){
*q = temp->link;
free(temp);
return;
}
else{
/* Delete the Intermdediate nodes */
old->link = temp->link;
free(temp);
return;
}
}
else{
/* Traverse the linked list */
old = temp;
temp = temp->link;
}
}
}
/* Display the data in the list */
void display(struct node *q){
printf("\n");
while(q != NULL){
printf("\n Data : %d \n",q->data);
q = q->link;
}
}
int main(){
struct node *p;
p = NULL; /* Empty linked list */
printf("\n No of items in linked list : %d\n",count(p));
append(&p,100);
append(&p,200);
append(&p,300);
append(&p,400);
append(&p,500);
append(&p,600);
append(&p,700);
append(&p,800);
display(p);
addatbeg(&p,10);
addatbeg(&p,20);
addatbeg(&p,30);
display(p);
addafter(p,0,1000);
addafter(p,6,2000);
addafter(p,9,3000);
display(p);
printf("\n No of items in the linked list : %d\n",count(p));
delete(&p,800);
delete(&p,500);
display(p);
printf("\n No of items in the linked list : %d\n",count(p));
return 0;
}
I'm having a problem in the addafter(),
In the function, we are creating another one copy of the pointer pointing to the heap and the changes made by the pointer will affect the pointer that is declared in the main as it is pointing to the same addressee of the heap.
So I thought that I will do the same for the addatbeg(), when I changed ** to * , the changes were not reflecting. Why is it so ?. Anyways if addatbeg(struct node *,int num), then also the pointer is pointing to the same heap.
The problem here is that p is defined in main() to be
struct node *p;
Now when you pass it to addatbeg(), you want the address that is stored at p to be changed because it will point to another node that has been added at the beginning of the list. However, when you use a definition like
addatbeg(struct node *,int num)
p is actually passed by value. In order to modify the p in main, you need to pass its address
addatbeg(struct node **,int num)
In addafter, you don't pass the address of p because you don't want your head pointer to change.
You can compare the situation to a simpler case. When you pass an integer by value you use foo(int), however when you want to modify the original integer you pass its address like foo(int *). The same thing is going on here with an extra level of dereferencing.
you need ** as need the value contained by head pointer, which would contain the address to first node of the linked list. You are passing the address of a address so you need a double pointer

C Linked lists with global variables

Hi I'm new to C and I'm struggling to get a linked list working I'm having to use global variables because I can't change the parameters of the function that is being called. I declare the struct and two global pointers to keep track of the root address and last address like this.
struct node {
char* pointer;
struct node *next;
};
struct node** rootNode;
struct node** lastNode;
Then inside the function I malloc a new struct and try to setup the first node in the list. To try and save the location of this node I think I'm assigning the global pointer lastNode to the pointer of root.
struct node *root = malloc(sizeof(struct node));
...
root->pointer=ptr;
root->next = 0;
rootNode = &root;
lastNode = &root;
Then I try to add aditional nodes by mallocing another node and then linking the previous node using the address stored in my lastNode pointer.
struct node *newNode = malloc(sizeof(struct node));
newNode->pointer=ptr ;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
However this doesn't really seem to work. When I run the following the program matches the first two items in the list but then returns null for all nodes after that. I've been stuck on this for 2 days now and any help would really be appreciated :)
struct node* test;
test = (*rootNode);
enter code here
while (test) {
if (test->pointer == ptr) {
printf("MATCH!!");
notFound = 0;
break;
}
else {
test = test->next;
}
}
EDIT A couple of people have asked me to supply some more code. This is the function in which I would like to create the linked list. It's called multiple times while my program is running and I'm trying to add a new node to my linked list every time it gets called. I've also included the global variables at the top.
struct node** rootNode;
struct node** lastNode;
int firstRun = 1;
struct node {
char* pointer;
struct node *next;
};
void malloc(size_t sz) {
size_t maxSize = (size_t)-1;
char * payloadPtr = NULL;
if (sz > maxSize - sizeof(struct node)+sizeof(int)) {
return ptr;
}
if (firstRun) {
struct node *root = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr = ptr+1;
root->pointer=payloadPtr;
root->next = 0;
rootNode = &root;
lastNode = &root;
firstRun = 0;
}
else {
struct node *newNode = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr =ptr+1;
newNode->pointer= payloadPtr;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
}
return payloadPtr;
}
There's a little clarification about changing the parameters into a function. In C you can only pass by pointers on function calls so if you want to modify the value of a struct node - you pass it like struct node * in the function. Similarly if you want to change the value of a struct node * in the function (as in allocate it or delete it) you may want to pass it like struct node **.
Your function prototype will probably have to look like this:
void addNode(struct node** root, char* value)
But you can also make that root node a local and also just a struct node * instead of struct node **. And then simply call it like:
addNode(&root, value);

dealing with array of linked list

My approach:
An array of fixed-length (lets say 20) each element is pointer to the first node of a linked list.
so i have 20 different linked list.
This is the structure:
struct node{
char data[16];
struct node *next;
};
My declaration for that array
struct node *nodesArr[20];
now to add a new node to one of the linked list, i do this:
struct node *temp;
temp = nodesArr[i]; // i is declared and its less than 20
addNode(temp,word); // word is declared (char *word) and has a value ("hello")
The addNode function:
void addNode(struct node *q, char *d){
if(q == NULL)
q = malloc(sizeof(struct node));
else{
while(q->next != NULL)
q = q->next;
q->next = malloc(sizeof(struct node));
q = q->next;
}
q->data = d; // this must done using strncpy
q->next = NULL;
}
and to print data from the array of linked list, i do this:
void print(){
int i;
struct node *temp;
for(i=0 ; i < 20; i++){
temp = nodesArr[i];
while(temp != NULL){
printf("%s\n",temp->data);
temp = temp->next;
}
}
}
now compiler gives no error, the program run and i pass the data to it, and when i call print it doesn't print any thing,,??
UPDATE::
after I edited the code (thx for you), i think the problem in the print function,, any idea ?
The problem lies in addNode(). When the list is empty you do:
q = malloc(sizeof(struct node));
but the scope of q is limited to addNode(). You should have declared addNode() as
void addNode(struct node **q, char *d)
and adjust your code accordingly:
*q = malloc(sizeof(struct node));
and so on...
When you pass struct node *q to addNode you are giving it an address for an element in your array. If you use malloc inside, then you are overwriting this variable q, which is local to the function and now points to something different, but you haven't changed your original array. Try using a pointer to pointer to node (struct node **q).
void addNode(struct node *q, char *d){
if(q == NULL)
q = malloc(sizeof(struct node));
Here's the problem.
The new value of q doesn't ever get out of the function, so your array of linked lists never gets updated.
Normally the solution here is to use a double-pointer:
void addNode(struct node **q, char *d){
if(*q == NULL)
*q = malloc(sizeof(struct node));
And call it like so:
addNode(&nodesArr[i],word);
Then, if you malloc a new node, the value in the array will be set to point to the new node.
struct node
{
int actual, estimated;
char c;
struct node *next;
} *head[4], *var[4], *trav[4];
void
insert_at_end (char c, int value, int value1)
{
struct node *temp;
temp = head[i];
var[i] = (struct node *) malloc (sizeof (struct node));
var[i]->actual = value;
//var1=(struct node *)malloc(sizeof(struct node));
var[i]->estimated = value1;
var[i]->c = c;
//printf("%d",var->estimated);
if (head[i] == NULL)
{
head[i] = var[i];
head[i]->next = NULL;
}
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
var[i]->next = NULL;
temp->next = var[i];
}
}

Resources