How to fix casting a pointer to an integer? - c

I'm writing a program that creates a doubly linked list out of an array. Here's the code so far:
#include<stdio.h>
#include<stdlib.h>
struct Node {
int data;
struct Node *next;
struct Node *previous;
}
struct Node *create_dll_from_array(int array[], int x) {
int i;
struct Node *newNode, *temp, *head;
for (i=0; i<x; i++) {
newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = *(array+i);
if (i=0) {
head = newNode;
temp = newNode;
newNode->next = NULL;
newNode->previous = NULL;
}
else {
*** temp->next = (struct Node*) newNode->data;
newNode->next = NULL;
*** newNode->previous = (struct Node*) temp->data;
temp = newNode;
}
}
return head;
}
int main(){
int array[5] = {11,2,7,22,4};
struct Node* head;
head = create_dll_from_array(array,5);
return 0;
}
So in the lines with ***, I'm getting the error: warning: cast to pointer from integer of different size
I don't know whether the program itself actually works, just asking about those two lines and why they aren't working. Thanks!

How to fix casting a pointer to an integer?
Don't assign an int to a pointer and then the need for casting is gone.
Assign a pointer to a pointer.
// temp->next = (struct Node*) newNode->data;
temp->next = newNode;

You can improve on these things:
Always initialize your pointer with NULL. This will guard you against the pointer pointing to an invalid address.
Do not hard code the array size value. Calculate it.
In the if condition you have used assignment =. Change that to equality check ==. If you will not do this, your program will crash.
just asking about those two lines and why they aren't working
It is because, temp->next points to a memory location of type struct node. You cant assign it an integer value (as you were doing). I have reproduced your full code below some of your lines commented.
#include<stdio.h>
#include<stdlib.h>
struct Node {
int data;
struct Node *next;
struct Node *previous;
};
struct Node *create_dll_from_array(int array[], int x) {
int i;
// struct Node *newNode, *temp, *head;
struct Node *newNode= NULL, *temp=NULL, *head=NULL;
for (i=0; i<x; i++) {
newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = *(array+i);
// if (i=0) { Its wrong
if (i==0) {
head = newNode;
temp = newNode;
newNode->next = NULL;
newNode->previous = NULL;
}
else {
// temp->next = (struct Node*) newNode->data; // issue
temp->next = (struct Node*) newNode;
newNode->next = NULL;
// newNode->previous = (struct Node*) temp->data; //issue
newNode->previous = (struct Node*) temp; //issue
temp = newNode;
}
}
return head;
}
int main(){
// int array[5] = {11,2,7,22,4};
int array[] = {11,2,7,22,4};
struct Node* head;
// head = create_dll_from_array(array,5);
head = create_dll_from_array(array,sizeof(array)/sizeof(*array));
return 0;
}
Few more optimization that you can do is that inside your create_dll function, the if condition is hit only for the first time. You can move that to else condition and make your else condition your if condition

Related

Can't insert a node at the beginning of a linked list using a void function

I m trying to insert a newNode at the beginning of a linked list in C language. I have tried other methods such as returing the newNode from the insertAtBeginnning function and then setting the head as that newNode in the main function & that works fine. But what I want to do is use a void function for the case and change the head there itself which is not working.
Here's the complete code :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void linkedListTraversal(struct Node *ptr)
{
while (ptr != NULL)
{
printf("element: %d\n", ptr->data);
ptr = ptr->next;
}
}
void insertAtBeginning(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = head;
head = newNode;
}
void insertAtIndex(struct Node *head, int data, int index)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
int i = 0;
while (i < index - 1)
{
temp = temp->next;
i++;
}
newNode->data = data;
newNode->next = temp->next;
temp->next = newNode;
}
void insertAtEnd(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode;
newNode->data = data;
newNode->next = NULL;
}
void insertAfterNode(struct Node *previous, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = previous->next;
previous->next = newNode;
}
int main()
{
struct Node *head;
struct Node *second;
struct Node *third;
struct Node *fourth;
// Allocate memory for the nodes of the linkedLists in the heap
head = (struct Node *)malloc(sizeof(struct Node));
second = (struct Node *)malloc(sizeof(struct Node));
third = (struct Node *)malloc(sizeof(struct Node));
fourth = (struct Node *)malloc(sizeof(struct Node));
// Link first and second nodes
head->data = 12;
head->next = second;
// Link second and third nodes
second->data = 98;
second->next = third;
// Link third and fourth nodes
third->data = 38;
third->next = fourth;
// Terminate the linkedList at the fourth node
fourth->data = 37;
fourth->next = NULL;
printf("Linked list before insertion\n");
linkedListTraversal(head);
insertAtBeginning(head, 20);
// insertAtIndex(head, 22, 3);
// insertAtEnd(head, 110);
// insertAfterNode(second, 27);
printf("Linked list after insertion\n");
linkedListTraversal(head);
return 0;
}
Here i have also used other cases of insertion in linked list and all are working fine instead of just insertAtBeginning function :(
Any help will be greatfull.
head is the entry point for your list. Inserting an element at the beginning should make head point to this new element. To do it from a void function, you have to pass the address of head so that head is modified by the function:
void insertAtBeginning(struct Node **head, int data)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
The call to the function will therefore be:
insertAtBeginning(&head, 20);
Another solution would be to have the function return the new address of head.
PS: we don't cast the return from malloc in C and we should check that it succeeded.

Linked List C: add node to beginning, unexpected '0' value

I am trying to add a new node to the end of a linked list, I am able to add something, but when I print it out the node has a value of '0'. I thought this might be happening because I may have neglected to initialise a variable somewhere, or forgot to allocate memory said variable. but I can't get it to work.
Here is my source code:
my Linked List/struct:
#include<stdio.h>
typedef char DATA;
struct Node {
DATA d;
struct Node *next;
};
my printList function:
void printList(struct Node **head) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
printf("Linked list:");
while (temp->next != NULL) {
printf( " \n %d ", temp->d);
temp = temp->next;
}
printf("\n");
}
my insertNodeAtEnd to end function:
// inset data at end
void insertNodeAtEnd(struct Node *head) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *currentNode, *temp;
temp = newNode;
currentNode = newNode;
printf("Enter a Node to insert at the end of the list \n");
scanf("%s", &newNode->d);
newNode->next = NULL;
if (head == NULL) {
head = newNode;
currentNode = newNode;
} else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
and my main():
int main() {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for (i = 0; i < 3; i++) {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
insertNodeAtEnd(head);
printList(&head);
return 0;
sorry for any messy code, I'm still reasonably new at this
Well, you have a couple of mistakes. Firstly, you need to add
temp->next = NULL;
before line insertNodeAtEnd(head);. The reason your code might work without this line is probably because your compiler initializes the pointer to NULL by default. For example in GCC you program is crashing without that line.Second problem is that you are defyning DATA type as a char, but reading it as int. It may cause crashing your application if processor working with big-engian addresses. You should change it to
typedef int DATA;
and also change
scanf("%s", &newNode->d);
to
scanf("%d", &newNode->d);
After that, change
while(temp->next!=NULL)
to
while(temp!=NULL)
because otherwise you are missing the last element. Then, you need to reorder a loop a little bit. This is the full working code with all fixes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode;
struct Node *temp;
temp = *head;
printf("Linked list:");
while(temp!=NULL)
{
printf( " \n %d ", temp->d);
temp = temp->next;
}
printf("\n");
}
// inset data at end
void insertNodeAtEnd(struct Node **headPointer)
{
struct Node *head = *headPointer;
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *currentNode, *temp;
temp = newNode;
currentNode = newNode;
printf("Enter a Node to insert at the end of the list \n");
scanf("%d", &newNode->d);
newNode->next = NULL;
if(head == NULL)
{
head = newNode;
currentNode = newNode;
}
else
{
temp = head;
while(temp->next!= NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
*headPointer = head;
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers: ");
for(i = 0; i < 3; i++)
{
if(i){
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
temp->next = newNode;
temp = temp->next;
scanf("%d", &temp->d);
}else{
scanf("%d", &temp->d);
}
}
temp->next = NULL;
insertNodeAtEnd(&head);
printList(&head);
return 0;
}
UPDATE
I added a two more fixes. as #BLUEPIXY pointed out, there are a few more OP's mistakes. I've already spotted them, but I didn't fix it because they were not essential to what causes OP's problem. But, anyway, the mistakes are following:
Firstly, if the list is empty, function insertNodeAtEnd will not update pointer to the list because you are passing pointer to head of the list instead of pointer of a pointer to the head. It can be fixed by adding ** to the function argument type.
Secondly, you don't need to allocate memory while printing a list. You obviously just copied the code to each function, even to functions which doesn't require inserting nodes (like printList).
The above script is updated script including these two fixes.

Linked List not printing

I am trying to create a simple linked list using C, I think I was able to construct the linked list itself, but when I try and print it, it prints the value of the last node instead of all the values in the list.
#include <stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
temp->next = NULL;
printf("%d \n", temp->d);
return 0;
}
Any help/tips would be greatly appreciated.
There are multiple problems in your code:
You are not creating the list properly. You are allocating memory for only one node and playing around with pointers improperly causing the linked list to be pointed to the same memory
You are not calling printList function at all
It is not clear why you are allocating memory again in printList whereas it should be printing the already created list
Also, no need to pass double pointer for printList as you are not modifying the list.
Though you should be understanding and doing the changes yourself, I am providing a below modified program which I hope will help you understand the mistakes in your code.
Please see the below modified version of the code
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
struct Node *createNode()
{
struct Node *newNode;
newNode = malloc(sizeof(struct Node));
if (NULL == newNode)
return NULL;
memset(newNode, 0, sizeof(struct Node));
return newNode;
}
int main()
{
struct Node *newNode = NULL;
struct Node *headNode = NULL;
struct Node *temp = NULL;
int i = 0;
int data = 0;
printf("Enter 3 numbers\n");
for( i = 0; i< 3; i++)
{
scanf("%d", &data);
newNode = createNode();
if (NULL == newNode)
break;
newNode->d = data;
if (headNode == NULL)
{
headNode = newNode;
temp = newNode;
}
else
{
temp->next = newNode;
temp = temp->next;
}
}
printList(headNode);
return 0;
}
Replace your code with the following code :-
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp->next!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
printList(head);
return 0;
}
Here you need to declare the newNode in the loop also while taking the input. As, the current value is over-writted, the old value is lossed and only the value of last node is printed.
Also while printing, check for temp->next!=Null instead of temp!=NULL

why modifying the data field change the other field in link list

I want to insert node one by one in createDDCL() method and print all elements in printDDClinkList() method,but there is some strange error in createDDCL() method:
//BiDirection link list
typedef struct DDCL{
int data;
struct DDCL *priv;
struct DDCL *next;
}*BiDirectionLink;
BiDirectionLink createDDCL(){//带头结点的双向循环链表
int n = 0,i=0;
BiDirectionLink head = (BiDirectionLink)malloc(sizeof(BiDirectionLink));
BiDirectionLink newNode,lastNodw;
head->next = head;
head->priv = head;
lastNodw = head;
printf("how many node do you want?\n:");
scanf("%d",&n);
for (; i<n; i++) {//append new node to the last
newNode = (BiDirectionLink)malloc(sizeof(BiDirectionLink));
newNode->priv = lastNodw;
newNode->next = head;//new node's next always head
head->priv = newNode;//th privious one of the head always the last
lastNodw->next = newNode;
newNode->data = i;
lastNodw = newNode;
}
return head;
}
detail!!!!!!!!!!!
void printDDClinkList(BiDirectionLink head){
BiDirectionLink node = head->next;
while (node->next != head) {
printf("%d ",node->data);
node = node->next;
}
}
void testDDCLinkList(){
printDDClinkList(createDDCL());
}
int main(int argc, const char * argv[])
{
testDDCLinkList();
return 0;
}
This is the problem: You are allocating only enough memory for a pointer, not the whole struct.
This is what you did:
newNode = (BiDirectionLink)malloc(sizeof(BiDirectionLink));
Which is the same as this:
newNode = (struct DDCL *)malloc(sizeof(struct DDCL *));
But, that's what you wanted to do:
newNode = (struct DDCL *)malloc(sizeof(struct DDCL));
My recommendation? Never typedef to pointers.

Syntax for pointer to pointer when passing to parameters (in C) [duplicate]

This question already has answers here:
pointer to a pointer in a linked list
(2 answers)
Closed 9 years ago.
Yesterday I was trying to implement a linked list and although it worked and I "sort of" understand, it fried my brain a little bit.
What is wrong with function addNode() here?
#include <stdio.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *createList();
void addNode(struct Node* head, int value); // Adds Node directly after head
void viewList(struct Node *head); // Outputs list starting from head
int main()
{
struct Node *head = createList();
addNode(head, 10);
addNode(head, 8);
addNode(head, 23);
addNode(head, 5);
addNode(head, 4);
addNode(head, 4100);
viewList(head); // I didn't upload here to save space
return 0;
}
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
void addNode(struct Node* head, int value)
{
if(head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = head;
head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = head;
head = newNode;
}
}
The reason I am confused is because that version of add node did not work whilst this one did...
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
and that was called in the main function using an amperand in front of the head node pointer
addNode(&head, 10);
The thing that also baffles me is this. I have written some practise functions that accepts a pointer in the parameter list and within the function, modifies what the pointer is pointing to. I never had to use this **pointer syntax.
It has to do with that parameters are passed by value. So in the first, non-working version, the pointer to head is passed by value so the variable is a local variable inside the function. Changes to local variables are not visible outside the function when the function returns.
However, in the second version you pass the pointer by reference, so the function knows where in memory the actual pointer is and can store directly in that memory.
ASCII-diagram time:
Lets say you have the following three variables:
int value1;
int *pointer1 = &value1;
int **pointer2 = &pointer1;
The memory for the variables look something like this:
+----------+ +----------+ +--------+
| pointer2 | --> | pointer1 | --> | value1 |
+----------+ +----------+ +--------+
So pointer2 points to pointer1, and pointer1 points to value1.
Using the dereference operator * on pointer2 will get the value of what pointer2 points to, i.e. pointer1.
Stylistic (don't repeat yourself) ::
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
You don't need the if/else ::
#include <stdlib.h>
void addNode(struct Node **head, int value)
{
struct Node *newNode = malloc(sizeof *newNode);
if ( !newNode) { error(); return;}
newNode->value = value;
newNode->next = *head; // Could be NULL, but we need a NULL anyway in that case
*head = newNode;
}
This here will not work well
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
after you allocate a node and have head pointing to it you set head to point to NULL.
Here it is:
You have a bug with createList
struct Node *createList()
{
struct Node *head = malloc(sizeof(*head));
head->value = 0; //< Probably you want this
head->next = NULL; //< You definitively wanted this
return head;
}
If you are adding nodes to the tail of the list, then addNode would look like:
void addNodeLast(struct Node* head, int value)
{
struct Node *tailNode;
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = NULL;
// Find the last node in the list
for (tailNode = head; tailNode->next; tailNode = tailNode->next);
tailNode->next = head->next;
}
If you are inserting nodes after the head:
void addNodeAfterHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head-next;
head->next = newNode;
}
If you are changing the head (making new head every time):
Node *addNodeNewHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head;
return newNode;
}
...
Node * head = createList();
head = addNodNewHead(head, 3);
head = addNodNewHead(head, 5);

Resources