Reputation: 93
So I started looking into Datastructures in C and wanted to code a Singly Linked List.
this is a small piece of it:
struct nodes {
int val;
struct nodes *next;
};
void insert(struct nodes *list, int val) {
struct nodes *tmp = (struct nodes*) malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
list = tmp;
}
int main() {
struct nodes *test;
insert(test, 5);
insert(test, 10);
printf("test %d\n", test->next->val);
}
Here I get totally wrong output. When I try writing a function where I don't have to pass in the structure pointer, it works like expected.
OUTPUT:
test 90053
P.S I'm still starting with C so don't judge too hard :D
Upvotes: 0
Views: 856
Reputation: 1765
You can go on this way:
struct nodes {
int val;
struct nodes* next;
};
nodes* insert(struct nodes* list, int val) {
struct nodes* tmp = (struct nodes*)malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
return tmp;
}
When experimenting with structures like that the 1st function you write --- I believe --- is list() not insert().
In every function that can change the start address of the list you must return the address or it would be lost. And since you only insert at the beginning you lost everything, as the start address is always changed..
In general do not use void
. At a minimum is a waste, often an error. Return something, like a completion status. See an implementation of list()
that returns... the size
int list(struct nodes* list)
{
struct nodes* p = list;
int N = 0;
while (p != NULL)
{
printf("#%d %d\n", N, p->val);
p = p->next; N += 1;
};
printf("\n");
return N;
}
int main() {
struct nodes* test = NULL;
int n = 0;
for(n = 800; n>0; n-= 100) test = insert(test, n);
n = list(test);
printf("At the end list() returned %d\n", n);
}
this way you have more info since the beginning.
#0 100
#1 200
#2 300
#3 400
#4 500
#5 600
#6 700
#7 800
At the end list() returned 8
#include <stdio.h>
#include <stdlib.h>
struct no
{
void* item;
struct no* next;
struct no* prev;
}; // no
typedef struct no Node;
typedef struct
{
char* name;
unsigned size;
unsigned limit;
Node* start;
Node* end;
} List;
struct nodes {
int val;
struct nodes* next;
};
struct nodes* insert(struct nodes*, int);
int list(struct nodes* L);
int main() {
struct nodes* test = NULL;
int n = 0;
for(n = 800; n>0; n-= 100) test = insert(test, n);
n = list(test);
printf("At the end list() returned %d\n", n);
}
struct nodes* insert(struct nodes* list, int val) {
struct nodes* tmp = (struct nodes*)malloc(sizeof(struct nodes));
tmp->val = val;
tmp->next = list;
return tmp;
}
int list(struct nodes* list)
{
struct nodes* p = list;
int N = 0;
while (p != NULL)
{
printf("#%d %d\n", N, p->val);
p = p->next; N += 1;
};
printf("\n");
return N;
}
As pointed in the comments, note that a list is not a node
. A list if a collection of nodes, and the nodes have a data payload. If the payload is a (void*)
then you have a really abstract data structure since it can load anything, from a single char
to a 100-fields structure
.
Think about the way you wrote it and the case you have 5 lists in your program: a mess it will turn into very fast. And compare with something like the code below
struct no
{
void* item;
struct no* next;
struct no* prev;
}; // no
typedef struct no Node;
typedef struct
{
char* name;
unsigned size;
unsigned limit;
Node* start;
Node* end;
} List;
Note that as you put more info into the List
things get easier: you have always a size, a limit, pointers to start and end, and so on
Upvotes: 0
Reputation: 211540
You're altering a local variable so there's no effect on the caller. What you might mean is to use a pointer to a pointer so that can be changed:
int main() {
struct nodes *test = NULL; // Don't forget to initialize
insert(&test, 5);
insert(&test, 10);
printf("test %d\n", test->next->val);
}
Where your function now looks like:
void insert(struct nodes **list, int val) {
struct nodes *tmp = malloc(sizeof(struct nodes)); // No need to cast malloc() in C
tmp->val = val;
tmp->next = *list;
*list = tmp;
}
Since list
is de-referenced (*list
) it actually alters the original value (that is pointed to) meaning your list head changes.
In your original code you never initialized list
, it's just some random garbage value, and because insert
can never change it, it stays as junk data. Accessing any data through that is undefined behaviour so you'll get junk data or a crash.
Upvotes: 3