How to obtain a pointer to pointer in C? - c

I'm supposed to write a function to remove the first node in a linked list.
List is defined like so:
struct ListNode{
int nInfo;
struct ListNode *next;
};
struct ListNode *createNode(int nInfo) {
ListNode *node;
node->nInfo = nInfo;
node->next = NULL;
return node;
}
void insertNode(struct ListNode **list, struct ListNode *node) {
//Sorting list after nInfo
struct ListNode *temp;
struct ListNode *tmpList = *list;
if(*list != NULL) { //List exists
while((tmpList->next != NULL)) {
if((tmpList->nInfo >= node->nInfo) && (tmpList->next->nInfo < node->nInfo)) {
break;
}
tmpList = tmpList->next;
}
//Found where to insert the node
temp = tmpList->next; //Saving old nextnode
tmpList->next = node; //Assigning new nextnode
node->next = temp; //Re-inserting old node
}
else{
*list = node;
}
}
The function for removing the first node looks like this:
void deleteFirst(struct ListNode **list) {
//Delete first node
struct ListNode *temppointer = *list;
if(temppointer == NULL)
return; //List is NULL
*list = temppointer->next;
}
I use the functions like so:
struct ListNode *list = createNode(100);
struct ListNode *node1 = createNode(50);
insertNode(list, node1); //Gives error, cannot convert ListNode* to ListNode**
deleteFirst(list); //Same error
I can't figure out how to obtain a pointer to the list pointer.

As we suspected, you forget to allocate memory for your nodes:
struct ListNode *createNode(int nInfo) {
ListNode *node;
node->nInfo = nInfo;
node->next = NULL;
return node;
}
Your *node is a pointer, but it still points to nothing. You must ask the heap for memory for your node:
ListNode *node = malloc(sizeof(ListNode));
Then in DeleteNode, you must return the memory to the heap, as you no longer need it:
void deleteFirst(struct ListNode **list) {
//Delete first node
struct ListNode *temppointer = *list;
if(temppointer == NULL)
return; //List is NULL
*list = temppointer->next;
free(temppointer); // release the memory.
}

Pay attention! The function you wrote for creating a node cannot work as it is: the node is allocated on the stack, in the context of the function, and it is invalid after the function has exited.
You have to allocate the memory for the node on the heap, using (p.e.) malloc. The function that remove the node from the list is responsable for its deallocation, usually using free.

[posting as an answer to get the formatting right]
Note: your insert() function is overly complex. It can be reduced to
void insertNode(struct ListNode **list, struct ListNode *node) {
for( ; *list ; list = &(*list)->next ) { //List exists
if(*(list)->nInfo >= node->nInfo) break;
}
//Found where to insert the node
node->next = *list;
*list = node;
}

#include <stdlib.h>
struct ListNode{
int nInfo;
struct ListNode *next;
};
struct ListNode *createNode(int nInfo) {
struct ListNode *node=malloc(sizeof(*node));
if(node){
node->nInfo = nInfo;
node->next = NULL;
}
return node;
}
void insertNode(struct ListNode **list, struct ListNode *node) {
// for safety
if(!list) return;
if(!node) return;
//Sorting list after nInfo
struct ListNode *temp;
struct ListNode *tmpList = *list;
if(tmpList!= NULL) { //List exists
while(tmpList->next) {
if(
((tmpList->nInfo)>= (node->nInfo))
&&
((tmpList->next->nInfo) < (node->nInfo))
) {
break;
}
tmpList = tmpList->next;
}
//Found where to insert the node
temp = tmpList->next; //Saving old nextnode
tmpList->next = node; //Assigning new nextnode
node->next = temp; //Re-inserting old node
}
else{
*list = node;
}
}
void deleteFirst(struct ListNode **plist) {
if(!plist) return;
struct ListNode *list=*plist;
if(!list) return;
*plist=list->next;
free(list);
return ;
}
void printNodes(char *title,struct ListNode *list){
printf("\n== %s\n",title);
while(list){
printf("\t%d\n",list->nInfo);
list=list->next;
}
printf("\n");
}
int main(){
struct ListNode *list = createNode(100);
struct ListNode *node1 = createNode(50);
insertNode(&list, node1);
printNodes("on start",list);
insertNode(&list, createNode(70));
printNodes("after add 70",list);
deleteFirst(&list);
printNodes("after del first",list);
}

Related

How to Use Typedef Structure Name with Pointer

I am trying to implement a linked list using the given structure for a bigger project. The structure is defined below:
typedef struct node {
unint32_t size; // = size of the node
struct node * link; // = .next pointer
} * ListNode;
I was able to implement a linked list using struct node *. But when I attempt to use ListNode like in the following program:
typedef struct node {
unint32_t size;
struct node * link;
} * ListNode;
void insert_node (ListNode * head, unint32_t size) {
ListNode new_node = (ListNode) malloc (sizeof(ListNode));
new_node->size = size;
new_node->link = NULL;
if (head == NULL) {
head = &new_node;
}
else {
ListNode current = *head;
while (current->link != NULL) {
current = current->link;
}
current->link = new_node;
}
}
int main (int argc, char const * argv[]) {
ListNode head = NULL;
insert_node (&head, 10);
insert_node(&head, 20);
ListNode ptr = head;
while (ptr != NULL) {
printf ("%d ", ptr->size);
}
printf ("\n");
return 0;
}
I get a segmentation fault. Why is that? It even says that struct node * and ListNode are incompatible pointers/types. I thought they were the same struct just named differently.
A little clarification
typedef struct node {
unint32_t size;
struct node * link;
} *ListNode;
creates a type called ListNode. It is a pointer to a struct node. It is not a struct node
So when you do
sizeof(ListNode)
you get the size of a pointer, not the size of struct node
You needed to do
sizeof(struct node)
A very common thing to do is this
typedef struct node {
uint32_ size;
struct node* link;
} *PListNode, ListNode;
this creates 2 types
PlistNode which is a pointer to a struct node
ListNode which is a struct node
the 'P' is a reminder that this is a pointer
so now you can do
PListNode pn = malloc(sizeof(ListNode));
Since you supply a struct node** (a ListNode*) to insert_node, you need to dereference it to assign to it.
You malloc the size of a struct node* (a ListNode) but you need to malloc the size of a struct node.
You also need to do ptr = ptr->link in the loop in main.
Example:
void insert_node(ListNode* head, uint32_t size) {
// corrected malloc, you don't want the sizeof a pointer but the
// size of a `node`:
ListNode new_node = malloc(sizeof *new_node);
new_node->size = size;
new_node->link = NULL;
if (*head == NULL) { // corrected check (dereference head)
*head = new_node; // corrected assignment
} else {
ListNode current = *head;
while (current->link != NULL) {
current = current->link;
}
current->link = new_node;
}
}
int main() {
ListNode head = NULL;
insert_node(&head, 10);
insert_node(&head, 20);
// the below loop had no exit condition before:
for(ListNode ptr = head; ptr; ptr = ptr->link) {
printf("%d ", ptr->size);
}
printf("\n");
}
Demo

C error: dereferencing pointer to incomplete type linked list

In my c program I creating a singly linked list where we have to insert a node using the prev node, I'm getting this error in my main() function:
Dereferencing pointer to incomplete type ‘struct Node’
I am not sure why is it giving that error.
while((temp->next != NULL) && (temp->next->data < randomNumData)) -- error here
typedef struct _Node
{
int data;
struct Node *next;
} ListNode;
ListNode *newList();
ListNode *insertNode(ListNode *prev, int data);
int main()
{
ListNode *head = newList();
int randomNumData;
ListNode *temp = head;
int i;
for(i = 0; i < 11; i++)
{
randomNumData = random()%1001;
while((temp->next != NULL) && (temp->next->data < randomNumData))
{
temp = temp->next;
}
temp->data = randomNumData;
head = insertNode(temp, randomNumData);
}
printList(head);
}
// returning the head of a new list using dummy head node
ListNode *newList()
{
ListNode *head;
head = malloc(sizeof(ListNode));
if(head == NULL)
{
printf("ERROR");
exit(1);
}
head->next = NULL;
return head;
}
ListNode *insertNode(ListNode *prev, int data)
{
ListNode *temp = prev;
prev->next = temp->next;
temp->next->data = data;
return temp;
}
You are missing underscore when declaring next.
typedef struct _Node
{
int data;
struct _Node *next;
} ListNode;
It looks like you don't have a struct called Node. Import it from other file or just implement it. C is good but it's not a magician so far.

simple linked list implementation logical error?

I have implemented a linked list code, but it seems that there is somewhere a logic error in my code, can anyone help me to fix this problem?
struct Node{
int val;
struct Node *next;
};
void add(struct Node *new_node, struct Node *head){
struct Node *new_n;
if( head == NULL){
head = new_node;
}
else{
new_n = head;
while(new_n){
new_n = new_n->next;
}
new_n = new_node;
}
}
void print(struct Node*n){
while(n != NULL){
fprintf(stderr, "val:%d addr%p \t next%p\n",n->val, n, n->next);
n=n->next;
}
}
void main (){
struct Node *head;
struct Node *node;
int i ;
for( i =1; i< 5; i++){
struct Node *node = malloc(sizeof(*node));
bzero(node,sizeof(*node));
node->val = i;
node->next =NULL;
add(node, head);
}
print(head);
}
This code doesn't print any values? What are the problems with this code?
[ I used: $gcc filename.c -o filename.o]
I see three problems:
1) head is never initialized
Use:
struct Node *head = NULL;
2) Changes to head inside the add function does not change head in main
Try
void add(struct Node *new_node, struct Node **head){
^^
and use *head in the function and call it like add(node, &head);
3) New elements are not added to the list.
Try:
void add(struct Node *new_node, struct Node **head) {
struct Node *new_n;
if (*head == NULL) {
*head = new_node;
}
else {
new_n = *head;
while (new_n->next) { // Notice - iterate until the next pointer is NULL
new_n = new_n->next;
}
new_n->next = new_node; // Notice
}
}
in doing this you return a pointer to the new head node and thus can iterate the new list containing your newer element at the end of the list.
struct Node{
int val;
struct Node *next;
};
*Node add(struct Node *new_node, struct Node *head)
{
struct Node *new_n;
if( head == NULL)
{
head = new_node;
}
else
{
new_n = head;
while(new_n)
{
new_n = new_n->next;
}
new_n = new_node;
}
return new_n;
}
void print(struct Node*n){
while(n != NULL){
fprintf(stderr, "val:%d addr%p \t next%p\n",n->val, n, n->next);
n=n->next;
}
}
void main (){
struct Node *head;
struct Node *node;
int i ;
for( i =1; i< 5; i++){
struct Node *node = malloc(sizeof(*node));
bzero(node,sizeof(*node));
node->val = i;
node->next =NULL;
*head = add(node, head);
}
print(head);
}

Linked list implementation in C(printing only last two nodes)

#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
void addLast(struct node **head, int value);
void printAll(struct node *head);
struct node *head1 = NULL;
int main() {
addLast(&head1, 10);
addLast(&head1, 20);
addLast(&head1, 30);
addLast(&head1, 40);
printAll(head1);
return 0;
}
void addLast(struct node **head, int value) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
(*head)->next = NULL;
} else {
struct node **temp = head;
while ((*temp)->next != NULL) {
*temp = (*temp)->next;
}
(*temp)->next = newNode;
newNode->next = NULL;
}
}
void printAll(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d->", temp->data);
temp = temp->next;
}
printf("\n");
}
addLast() will append the new node at the end of the list, with printAll(), I am printing entire list.
Every time when I am printing the list, I can only see the last two nodes.
Can anyone please help, why loop is not iterating over entire list ?
The function addLast is too complicated and as result is wrong due to this statement
*temp = (*temp)->next;
in the while loop. It always changes the head node.
Define the function the following way
int addLast( struct node **head, int value )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = value;
newNode->next = NULL:
while( *head ) head = &( *head )->next;
*head = newNode;
}
return success;
}
Take into account that there is no need to declare the variable head1 as global. It is better to declare it inside the function main.
Also all the allocated memory should be freed before exiting the program.

trouble updating tail pointer in queue adt using singly linked list

i am trying to make a queue library that is based on a linked list library i already made. specifically i am having troubles updating the tail pointer in the queue structure after i add a new node to the linked list.
linked list structure:
struct listNode {
int nodeLength;
int nodeValue;
struct listNode *next;
};
typedef struct listNode node;
queue structure:
struct QueueRecord {
node *list;
node *front;
node *back;
int maxLen;
};
typedef struct QueueRecord queue;
so here is my add function in the queue library
void add(queue currentQueue, int data){
addTail(currentQueue.list, data, data+5);
currentQueue.back = currentQueue.back->next;
}
and the addTail function from the linked list library
void addTail (node *head, int value, int length) {
node *current = head;
node *newNode = (struct listNode *)malloc(sizeof(node));
newNode = initNode(value, length);
while (current->next != NULL)
current = current->next;
newNode->next = NULL;
current->next = newNode;
}
so again my problem is the tail pointer is not getting set to the last node in the list. it is remaining in the same place as the head pointer. ive been researching this for hours trying to see if im just missing something small but i cant find it. if more code or explanation is needed to understand my problem i can provide it.
how a queue is created:
queue createQueue(int maxLen){
queue newQueue;
newQueue.list = createList();
newQueue.front = newQueue.list;
newQueue.back = newQueue.list;
newQueue.maxLen = maxLen;
return newQueue;
}
node *createList (){
node *head = NULL;
head = (struct listNode *)malloc(sizeof(node));
head->next = NULL;
return head;
}
node *initNode (int value, int length){
node *newNode = NULL;
newNode = (struct listNode *)malloc(sizeof(node));
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
return newNode;
}
void add(queue currentQueue, int data){
You are passing a copy of the queue struct to add, so only the copy's members are changed. You need to pass a queue* to the function to be able to change the members of the queue itself.
void add(queue *currentQueue, int data){
if (currentQueue == NULL) {
exit(EXIT_FAILURE);
}
addTail(currentQueue->list, data, data+5);
currentQueue->back = currentQueue->back->next;
}
and call it as add(&your_queue);
In your addTail function, you should check whether head is NULL too.
And with
node *newNode = (struct listNode *)malloc(sizeof(node));
newNode = initNode(value, length);
in addTail, you have a serious problem. With the assignment newNode = initNode(value, length);, you are losing the reference to the just malloced memory.
If initNode mallocs a new chunk of memory, it's "just" a memory leak, then you should remove the malloc in addTail.
Otherwise, I fear initNode returns the address of a local variable, à la
node * initNode(int val, int len) {
node new;
new.nodeValue = val;
new.nodeLength = len;
new.next = NULL;
return &new;
}
If initNode looks similar to that, that would cause a problem since the address becomes invalid as soon as the function returns. But your compiler should have warned you, if initNode looked like that.
Anyway, without seeing the code for initNode, I can't diagnose the cause.
But if you change your addTail to
void addTail (node *head, int value, int length) {
if (head == NULL) { // violation of contract, die loud
exit(EXIT_FAILURE);
}
node *current = head;
node *newNode = malloc(sizeof(node));
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
it should work.
However, since you have pointers to the first and the last node in the list, it would be more efficient to use the back pointer to append a new node,
void add(queue *currentQueue, int data){
node *newNode = malloc(sizeof *newNode);
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = data;
newNode->nodeLength = data+5;
newNode->next = NULL;
currentQueue->back->next = newNode;
currentQueue->back = newNode;
}
since you needn't traverse the entire list to find the end.
A simple sample programme
#include <stdlib.h>
#include <stdio.h>
struct listNode {
int nodeLength;
int nodeValue;
struct listNode *next;
};
typedef struct listNode node;
struct QueueRecord {
node *list;
node *front;
node *back;
int maxLen;
};
typedef struct QueueRecord queue;
node *createList (){
node *head = NULL;
head = (struct listNode *)malloc(sizeof(node));
head->next = NULL;
return head;
}
void addTail (node *head, int value, int length) {
if (head == NULL) { // violation of contract, die loud
exit(EXIT_FAILURE);
}
node *current = head;
node *newNode = malloc(sizeof(node));
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
queue createQueue(int maxLen){
queue newQueue;
newQueue.list = createList();
newQueue.front = newQueue.list;
newQueue.back = newQueue.list;
newQueue.maxLen = maxLen;
return newQueue;
}
void add(queue *currentQueue, int data){
if (currentQueue == NULL) {
exit(EXIT_FAILURE);
}
addTail(currentQueue->list, data, data+5);
currentQueue->back = currentQueue->back->next;
}
int main(void) {
queue myQ = createQueue(10);
for(int i = 1; i < 6; ++i) {
add(&myQ, i);
printf("list: %p\nfront: %p\nback: %p\n",
(void*)myQ.list, (void*)myQ.front, (void*)myQ.back);
}
node *curr = myQ.front->next;
while(curr) {
printf("Node %d %d, Back %d %d\n", curr->nodeValue,
curr->nodeLength, myQ.back->nodeValue, myQ.back->nodeLength);
curr = curr->next;
}
while(myQ.list) {
myQ.front = myQ.front->next;
free(myQ.list);
myQ.list = myQ.front;
}
return 0;
}
works as expected, also with the alternative add implementation.
i think you never initialized back, so back->next is some random pointer?

Resources