** pointer and * pointer in C [duplicate] - c

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

Related

Program to create a linked list not working

Only the head element gets printed and no element gets printed further.
My guess is that the code inside else{.....} inside the createLinkedList(int n) function portion isn't seem to be doing it's job.
Code is below :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node * next;
}*head;
void createLinkedList(int n)
{
int i;
struct Node *temp, *p;
for(i=1; i<=n; i++)
{
// First thing we do is create an ISOLATED NODE WHICH IS NOT LINKED TO ANYTHING
temp = (struct Node *)malloc(sizeof(struct Node));
printf("Now enter your element %d of linked list: ",i);
scanf("%d",&(temp->data));
temp->next = NULL;
// ISOLATED NODE CREATED. SINCE THIS IS UNLINKED, WE MUST STORE IT'S POINTER VARIABLE TO NULL
if(head == NULL) // Meaning our Linked List is empty
head = temp;
else // Meaning our Linked List is not empty. Has at least one element.
{
p = head;
while(p != NULL)
p = p->next; // Accessing Last pointer of Linked List
p = temp; // THAT IOSOLATED NODE Is Hereby Connected to our final Linked LIST Element
}
printf("\n");
}
}
int main()
{
head = NULL;
printf("Enter the length of your linked list: ");
int n;
scanf("%d", &n);
printf("\n");
createLinkedList(n);
return 0;
}
Change while(p != NULL) p = p->next;
to
while(p->next != NULL)
p = p->next;
That would give you the last pointer position where you can insert your node. Right now, p will be null at the end of the iteration.
After that you need to do p->next = temp so that your newly created node is added to the linked list.
Instead of looping in else block, we can track the tail pointer for last node in linked list. Below is modified code:
void createLinkedList(int n)
{
int i;
struct Node *temp, *tail;
for(i=1; i<=n; i++)
{
// First thing we do is create an ISOLATED NODE WHICH IS NOT LINKED TO ANYTHING
temp = (struct Node *)malloc(sizeof(struct Node));
printf("Now enter your element %d of linked list: ",i);
scanf("%d",&(temp->data));
temp->next = NULL;
// ISOLATED NODE CREATED. SINCE THIS IS UNLINKED, WE MUST STORE IT'S POINTER VARIABLE TO NULL
if(head == NULL) // Meaning our Linked List is empty
{
head = temp;
tail = temp;
}
else // Meaning our Linked List is not empty. Has at least one element.
{
tail->next = temp; // THAT IOSOLATED NODE Is Hereby Connected to our final Linked LIST Element
tail = temp;
}
printf("\n");
}
}
int main()
{
head = NULL;
printf("Enter the length of your linked list: ");
int n;
scanf("%d", &n);
printf("\n");
createLinkedList(n);
return 0;
}
your code working but you lose the addresses of the next nodes when you are using while(p != NULL) so you should change it to while(p->next != NULL){p=p->next;}{p->next=temp;}.

How to print all the nodes in a circular linked list in C

I'm trying to implement a circular linked list in C, however I cant seem to print the nodes one by one. Below is the code for assigning the values and then printing them. Whenever I run it, all it prints out is "NULL". I would like to know what should i do so that it prints out "1 -> 2 -> 3 -> ...."
void tail_insert(struct Node * head, struct Node * tail, int num){
struct Node * p = (struct Node*) malloc(sizeof(struct Node));
p->info = num;
p->next = head;
if (head == NULL) {
head = p;
tail = head ;
}
else{
tail->next = p;
tail = p;
}
}
void print_list(struct Node * head)
{
struct Node * current = head;
while (current != NULL)
{
printf("%d -> ", current->info);
current = current->next;
}
printf("NULL\n");
}
int main(){
struct Node * head = NULL, * tail = NULL;
int num = 0;
int length;
int deletespace;
scanf("%d %d", &length, &deletespace);
for (int i = 1; i < length+1 ; i++){
tail_insert(head, tail, i);
}
print_list(head);
The reason you're not getting nodes printed is because of how pass by value works. When you call tail_insert, you're passing a basic pointer. Dereferencing and modifying this inside the function would modify the values pointed to by head and tail, but not carry changes to the pointers themselves outside the function.
One way of fixing this is to change the head and tail parameters to be pointers to pointers (**) and passing the addresses of those variables where you call the function in main.

Issues with C linked list

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;
.
.
}

why replacing *s with **s in SortedMerge() causes the program to crash?

while debugging i found that replacing **s by *s makes the program work correctly, but i dont understand why **s causes eroor in SortedMerge() function, please help
#include<stdio.h>
#include<stdlib.h>
/* Link list node */
struct node
{
int data;
struct node* next;
};
/* function prototypes */
struct node* SortedMerge(struct node* a, struct node* b);
void FrontBackSplit(struct node* source,
struct node** frontRef, struct node** backRef);
/* sorts the linked list by changing next pointers (not data) */
void MergeSort(struct node **head)
{
/*if list empty or contains one element, return head*/
if((*head==NULL)||((*head)->next)==NULL)
return *head;
/*if control here, implies, atleast 2 nodes present in ll*/
struct node* a=NULL;
struct node* b=NULL;
FrontBackSplit(*head,&a,&b);
MergeSort(&a);
MergeSort(&b);
*head=SortedMerge(a,b);
}
/* See http://geeksforgeeks.org/?p=3622 for details of this
function */
struct node* SortedMerge(struct node* first,struct node* second)
{
if((first==NULL)&&(second==NULL))
return NULL;
if(first==NULL)
return (second);
if(second==NULL)
{
return (first);
}
/*first and second list both have elements*/
struct node **s=NULL;
struct node *z=NULL;
while((first!=NULL)&&(second!=NULL))
{
if(*s==NULL)
{
*s = malloc(sizeof(struct node));
z = *s;
}
else
{
z->next = malloc(sizeof(struct node));
z = z->next;
}
if(first->data<=second->data)
{
z->data = first->data;
first = first->next;
}
else
{
z->data = second ->data;
second = second ->next;
}
}
while(first!=NULL)
{
z->next = malloc(sizeof(struct node));
z = z->next;
z->data = first->data;
first = first->next;
}
while(second!=NULL)
{
z->next = malloc(sizeof(struct node));
z = z->next;
z->data = second->data;
second = second->next;
}
z->next=NULL;
return *s;
}
/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves,
and return the two lists using the reference parameters.
If the length is odd, the extra node should go in the front list.
Uses the fast/slow pointer strategy. */
void FrontBackSplit(struct node* head,struct node **first,struct node **last)
{
struct node *slow_ptr=head;
struct node *fast_ptr=head->next;
if((head==NULL)||(head->next==NULL))
{
*first=head;
*last=NULL;
return;
}
while((fast_ptr!=NULL)&&(fast_ptr->next!=NULL))
{
fast_ptr=fast_ptr->next->next;
slow_ptr=slow_ptr->next;
}
*last=slow_ptr->next;
slow_ptr->next=NULL;
*first=head;
return;
}
/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves,
and return the two lists using the reference parameters.
If the length is odd, the extra node should go in the front list.
Uses the fast/slow pointer strategy. */
/* Function to print nodes in a given linked list */
void printList(struct node *node)
{
while(node!=NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
/* Function to insert a node at the beginging of the linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* Drier program to test above functions*/
int main()
{
/* Start with the empty list */
struct node* res = NULL;
struct node* a = NULL;
/* Let us create a unsorted linked lists to test the functions
Created lists shall be a: 2->3->20->5->10->15 */
push(&a, 15);
push(&a, 10);
push(&a, 5);
push(&a, 20);
push(&a, 3);
push(&a, 2);
/* Sort the above created Linked List */
MergeSort(&a);
printf("\n Sorted Linked List is: \n");
printList(a);
getchar();
return 0;
}
here is the working SortedMerge() function, that i replaced..
struct node* SortedMerge(struct node* a, struct node* b)
{
struct node* result = NULL;
/* Base cases */
if (a == NULL)
return(b);
else if (b==NULL)
return(a);
/* Pick either a or b, and recur */
if (a->data <= b->data)
{
result = a;
result->next = SortedMerge(a->next, b);
}
else
{
result = b;
result->next = SortedMerge(a, b->next);
}
return(result);
}
The split function divides the list into two pieces; no memory is allocated or freed. (Actually *head == *a after that, but that doesn't matter).
The merge function ought to be the inverse of split: combine two pieces into one list, without allocating or freeing. However it contains malloc statements. This must be an error; you should be merging the two lists by adjusting which element points to which next element.
It might be simpler to change your interface: just have split(struct node **a, struct node **b) that has pre-req *b = NULL and it moves half of a's nodes to b; and then merge(struct node **a, struct node **b); that moves all of b's nodes to a.

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