Simple link list program in C - c

Simple code of Link List implementation in C .
Is it correct way to write or I am missing anything ? Is free section is ok?
typedef struct box{// data type definition
int data;
struct box* next;
} node; // "node"
node* node1 = (node *)malloc( sizeof(node));// heap memory allocation for node1
if(node1 != NULL){ // ( safety check)
node1->data = 1;//assign value
node1->next = NULL;// doesn't point to anyone
}
node* node2 =(node*)malloc(sizeof(node));// node 2 work
if(node2 != NULL) {
node2 ->data = 2;
node2->next = NULL;
}
node1->next = node2;//first connection
node2->next = NULL;//second connection
for(node *tmp =node1; tmp !=NULL; tmp=tmp->next){// printing value in nodes using *tmp pointer
printf("%i\n",tmp->data );
}
free(node1);//delete node1 allocation on heap
free(node2);//delete node 2 allocation on heap

In this declaration
struct box{// data type definition
int data;
struct box* next;
} node; // "node"
you declared the variable node of the type struct box that is not further used.
It seems you mean a typedef declaration like
typedef struct box{// data type definition
int data;
struct box* next;
} node; // "node"
As a result these statements
node* node1 = (node *)malloc( sizeof(node));
node* node2 =(node*)malloc(sizeof(node));
shall produce compilation errors.
If your list is supposed to contain for example 100 nodes will you declare 100 variables node1 ,..., node100?
You need to write a separate function that includes new nodes in the list.
These statements
node1->next = node2;//first connection
node2->next = NULL;//second connection
can invoke undefined behavior if either pointer is equal to NULL.

Related

LinkedList in C error

I am attempting to write a LinkedList in C. Here are my two structs
struct node{
int key;
int value;
struct node *next;
};
struct LinkedList {
struct node *head;
};
And here is how I create a new node.
void createNode(int key, int value) {
struct node *new_node;
new_node->key = key;
new_node->value = value;
new_node->next = lList->head;
lList->head = new_node;
}
I am trying to traverse through the LinkedList using the function below.
void traverseNode(struct LinkedList *lList) {
struct node current = *lList->head;
while(current != NULL) {
printf("%i", current->key);
current = current->next;
}
}
However, I keep getting an error saying
invalid operands to binary expression ('struct node'
and 'void *')
in relation to my while expression.
Also, I get an error for the
printf("%i", current->key);
current = current->next
with the error being
member reference type 'struct node' is not a pointer;
maybe you meant to use '.'
I am confused because I thought in my node struct, the *next was defined as a pointer and could therefore be accessed only using the indirection(->) syntax.
I am a beginner to pointers, so any help is appreciated.
You cant compare NULL with non-pointer type.
Declare variable current as pointer + remove dereference of head and it will compile
struct node * current = lList->head;
^ ^
while(current != NULL) // Now you can compare them
You are getting SEGFAULT because you are dereferencing uninitialized pointer. Allocate enough memory on heap (dynamic storage duration).
struct node *new_node = malloc(sizeof(struct node));
Since current is pointer
printf("%i", current->key);
current = current->next;
should be OK now.
As the error states current is a structure, not the pointer
change it to struct node *current = lList -> head;
remember that pointer itself does not have the storage for the referenced object
do{
printf("%i", current->key);
current = current->next;
} while(current != NULL)
doing this instead will check if your on the last node by seeing if the next node is null rather than the whole structure
void createNode(int key, int value) {
struct node *new_node; // you need to malloc here
new_node->key = key;
new_node->value = value;
new_node->next = lList->head;
lList->head = new_node;
}
You must malloc before access a pointer.
struct node *new_node = (struct node*)malloc(sizeof(struct node));
Also change like,
struct node current = *lList->head;
into,
struct node *current = *lList->head;

Incompatible pointer type error using structs

I am new to programming. I am trying to learn C and pointers, but it is giving me much trouble.
I got the following error trying to implement a singly linked list. I searched online, and I couldn't find someone who had an error just like mine, or perhaps I just didn't couldn't make sense of it with my problem.
The following is the error I received:
warning: incompatible pointer types initializing 'NODE *'
(aka 'struct node *') with an expression of type 'struct NODE '
[-Wincompatible-pointer-types]
NODE temp = (*l)->head;
NODE* temp = (*l)->head;
In main, I passed the address of the variable of type LIST. So, I thought I had to dereference 'l', to get the address of where the LIST type is located, then I had to dereference with an arrow to get the address of where the NODE is located. Where am I confused? I do appreciate the help.
Below you will see the code I have written:
typedef struct node {
int value;
struct node* next;
}NODE;
typedef struct list{
struct NODE* head;
}LIST;
void insert(LIST** l, int x){
if((*l)->head == NULL){
NODE* new_Node = (NODE*) malloc(sizeof(NODE));
new_Node->next = NULL;
new_Node->value = x;
}
NODE* temp = (*l)->head;
while(temp->next != NULL){
temp=temp->next;
}
NODE* new_Node = (NODE*) malloc (sizeof(NODE));
temp->next = new_Node;
new_Node->next = NULL;
new_Node->value = x;
}
int main(){
LIST *l = (LIST*) malloc(sizeof(LIST));
insert(&l, 5);
return 0;
}
I guess your problem is here :
typedef struct list
{
struct NODE* head;
}LIST;
just remove struct keyword before NODE
typedef struct list
{
NODE* head;
}LIST;
or
typedef struct list
{
struct node* head;
}LIST;
Also you need to initialize the head with NULL to make this condition to wwork
if((*l)->head == NULL) .....
so when you create your list add l->head = NULL;
LIST *l = malloc(sizeof(LIST));
l->head = NULL;
And the last one (i hope) when you create your first node, you forget to assign head to it, and return in order not to add the first element twice
if((*l)->head == NULL)
{
NODE* new_Node = malloc(sizeof(NODE));
new_Node->next = NULL;
new_Node->value = x;
(*l)->head = new_Node;
return;
}
And BTW, don't cast malloc results in C
This:
typedef struct list{
struct NODE* head;
}LIST;
Should be this:
typedef struct list{
NODE* head;
}LIST;
Tested and compiles fine with that change.
Your use of *l is correct. The problem is with the line:
NODE* temp = (*l)->head;
The left-hand side is NODE *, which is the same as struct node *, however the right-hand side is struct NODE *.
C is case-sensitive, struct node and struct NODE are different types. Also, the namespace of struct tags is separate to that of other types, so NODE and struct NODE are also different types.
I think you meant, in LIST's definition, that struct NODE* head; should be NODE* head;. There is no warning generated on that line, because in C it's legal to implicitly declare a struct type just by mentioning it (i.e. this line declares the new type struct NODE also).
There is code repetition in your insert function. You should not use the struct keyword before NODE in the second typedef statement because NODE is already an alias for the type struct node. That's why you are getting the warning mentioned in your question. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc?
I suggest the following changes to your code.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *next;
} NODE;
typedef struct list {
NODE *head;
} LIST;
void insert(LIST **l, int x) {
// do not cast the result of malloc.
// also, do not repeat the type on the rhs.
// create the new node to be inserted
NODE *new_Node = malloc(sizeof(*new_Node));
new_Node->next = NULL;
new_Node->value = x;
NODE *temp = (*l)->head;
// check if the head of the list is empty
// if yes, simply assign the new node to head
// and return
if(temp == NULL) {
(*l)->head = new_Node;
return;
}
// reach the last node in the list
while(temp->next != NULL)
temp = temp->next;
// insert the new node to the end of the list
temp->next = new_Node;
}
int main(void) {
LIST *l = malloc(sizeof(*l));
insert(&l, 5);
insert(&l, 10);
// print the value of the head node
printf("%d\n", l->head->value);
// print the value of the next node
printf("%d\n", l->head->next->value);
NODE *head = l->head;
NODE *temp = NULL;
// free the nodes in the list
while(head != NULL) {
temp = head;
head = head->next;
free(temp);
}
// free the pointer to the
// head of the list
free(l);
return 0;
}

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);

Assignment from incompatible pointer type in C

I keep getting an "Assignment from incompatible pointer type" and I can't figure out why. I thought it looked right. I'm just trying to do the basics of a linked list in C.
typedef struct{
int id;
struct node *next;
} node;
node *root = NULL; // Sets up a root node when the program starts.
create nodes(int id){
if(root == NULL){
root = (node*)malloc(sizeof(node));
root-> id = -1;
node *nextNode;
nextNode = (node*)malloc(sizeof(node));
nextNode -> id = id;
root-> next = nextNode; // This line is throwing an error.
}
}
I feel like it's something simple but I can't put my finger on it...
Your struct is actually an unnamed struct typedef-d to node, but you're trying to refer to it as struct node later (which is not the same as your node typedef). Quick fix is to simply give the struct a name:
typedef struct node {
int id;
struct node *next;
} node;
Or, if you prefer (and this is completely stylistic), remove the typedef and correct your other references to the struct:
struct node {
int id;
struct node *next;
};
struct node *root = NULL;
create nodes(int id){
if(root == NULL){
root = malloc(sizeof(struct node));
root->id = -1;
struct node *nextNode;
nextNode = malloc(sizeof(struct node));
nextNode->id = id;
root->next = nextNode;
}
}
Four points here:
First. Add a name of the struct node, if you must include pointer in the field of the struct (as #JamesMcLaughlin pointed out above). For example:
typedef struct nodetag {
int id;
struct nodetag *next;
} node;
Second. Make sure you are using the variable type create as intended. I assume user-defined variable type create exist within your #define or somewhere else. If not, this will cause a compiler error. Even if you did, this won't compile as you don't have a return statement that returns create.
Third. Include node *root = NULL; within your function nodes. Otherwise, function nodes won't recognize the variable root and results in a compiler error.
Fourth. Declare local variables in the beginning of the function. The line struct node *nextNode; will cause a compiler error for C89 as C89 does not allow type-declaration after statements. C99, however, allows such practice. It's advised to declare all of the local variables in the beginning of the function to be compatible with both C89 and C99.
Try this
struct node{
int id;
struct node *next;
} ;
struct node *root = NULL; // Sets up a root node when the program starts.
/* Return type is missing in your code*/ create_nodes(int id){
if(root == NULL){
root = (struct node*)malloc(sizeof(struct node));
root-> id = -1;
struct node *nextNode;
nextNode = (struct node*)malloc(sizeof(struct node));
nextNode -> id = id;
root-> next = nextNode; // This line is throwing an error.
}
}

Casting items to end of linked list in C

EDIT*(8:14 PM) - Sorry I corrected my code and made this instead a method so it can be more easily understood.
I am not sure how to properly cast a struct when adding to the end of a linked list. Compiling this code gives me an cast warning at the very last line. This may be the reason why the rest of my code does not properly function.
For example:
#include <stdlib.h>
typedef struct {
int data;
struct node *next;
} node;
node *HEAD = NULL;
node *addNode(int num)
{
if (HEAD == NULL) {
HEAD = (node *)malloc(sizeof(node));
HEAD->next = NULL;
HEAD->data = num;
}
else {
node *newNode;
newNode = (node *)malloc(sizeof(node));
newNode->data = num;
newNode->next = NULL;
node *iter;
iter = (node *)malloc(sizeof(node));
iter = (node *)HEAD;
while(iter->next != NULL)
iter = (node *)iter->next;
iter->next = newNode; //warning : warning: assignment from incompatible pointer type
}
return HEAD;
}
Make sure to include stdlib.h -- needed to use malloc
fix all occurance of wordNode to be node -- wordNode is undefined in your program
create a struct and typedef both named node -- standard trick for self referential structs
and then all your warnings goes away;
#include <stdlib.h>
struct node{
int data;
struct node *next;
};
typedef struct node node;
node *HEAD = NULL;
int main(int argc, char*argv[]) {
int x = 1;
int y = 2;
if(HEAD == NULL)
{
HEAD = (node *)malloc(sizeof(node));
HEAD->next = NULL;
HEAD->data = x;
}
else
{
node *newNode;
newNode = (node *)malloc(sizeof(node));
newNode->data = y;
newNode->next = NULL;
node *iter;
iter = (node *)malloc(sizeof(node));
iter = (node *)HEAD;
while(iter->next != NULL)
iter = (node *)iter->next;
iter->next = newNode; //warning : warning: assignment from incompatible pointer type
return 0;
}
}
The problem is that you declare "next" to be a pointer to "struct node" before the struct is completely defined, so "next" points to an undefined structure. If you change "typedef struct{" to "typedef struct node{", that error will be gone.
There is a number of problems with your code. The first one would be casting the return value of malloc and improperly referring to the size of the type for which you want some space to be allocated :
HEAD = (node *)malloc(sizeof(node));
should be replaced by
HEAD = malloc(sizeof(*HEAD))
Since the conversion from void* to any other type is always defined and implicit in C, you don't get any warnings about a needed cast. Specifying sizeof(*HEAD) makes the compiler automatically choose the type of HEAD at compile time, thus reducing the needed work should the type ever change.
You should also remember that some compilers don't like anonymous structures (i.e. structures without a name declared). Therefore, the code
typedef struct{
int data;
struct node *next;
} node;
should be replaced by
typedef struct _node {
int data;
struct _node *next;
} node;
Which declares a structure called _node, typedefed to the type called node. And also fixes the circular reference.
On top of all that, you don't need to malloc any space for the iter.

Resources