I am trying to create a doubly linked list in C but it doesn't work and I don't know why. It prints only the last element that I introduce. I do not see any problem at the part of code that creates the list. Maybe you can see it?
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
struct node *prev;
}NodeT;
struct d_linked_list
{
NodeT *first;
NodeT *last;
};
int main()
{
int d;
struct d_linked_list *l;
NodeT *p,*q;
p=(NodeT*)malloc(sizeof(NodeT));
q=(NodeT*)malloc(sizeof(NodeT));
l->first=NULL;
l->last=NULL;
while (fscanf(stdin,"%d",&d)!=EOF)
{
p->data=d;
if (l->first==NULL)
{
l->first=p;
l->last=p;
p->next=NULL;
p->prev=NULL;
}
else
{
l->last->next=p;
p->prev=l->last;
l->last=p;
}
}
l->last->next=NULL;
for (q=l->first;q!=NULL;q=q->next)
printf("%d ",q->data);
return 0;
}
As so often, there are a number of problems, some of them already identified in other answers or in comments and some (I think) not identified before:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
struct node *prev;
}NodeT;
struct d_linked_list
{
NodeT *first;
NodeT *last;
};
So far, so good.
int main()
{
int d;
struct d_linked_list *l;
You don't allocate space for l. It would probably be simpler (maybe better, therefore) to use:
struct d_linked_list head; // Or maybe list instead of head
and then refer to head in your code instead of l; you could also use l = &head; without further changes.
NodeT *p,*q;
p=(NodeT*)malloc(sizeof(NodeT));
q=(NodeT*)malloc(sizeof(NodeT));
You never use the space allocated for q and you eventually overwrite it, thus leaking. You should check that malloc() worked, doing something appropriate (stop with an error message?) if it has failed.
l->first=NULL;
l->last=NULL;
while (fscanf(stdin,"%d",&d)!=EOF)
You should check that you got one integer with while (fscanf(stdin, "%d", &d) == 1); the loop breaks on EOF or on a conversion failure.
{
p->data=d;
You allocated p before the loop, but each subsequent entry is overwriting the same space. You need to allocate a new node for each value you read. (This was not previously identified as an issue — though I see Filipe Gonçalves added it to his answer while I was typing mine.)
if (l->first==NULL)
{
l->first=p;
l->last=p;
p->next=NULL;
p->prev=NULL;
}
else
{
l->last->next=p;
p->prev=l->last;
l->last=p;
}
}
Superficially, the code above looks OK; I've not run it, so there could be issues I've not spotted.
I noted 'not thoroughly checked' and indeed there are problems, as Filipe pointed out. The if clause is OK, I think, but the else clause needs to set p->next = NULL;. In general, it is a good idea to create the node completely: p->data = d; p->next = NULL; p->prev = NULL: and then hook the node into the list.
l->last->next=NULL;
This line should be unnecessary. At the end of each cycle of the loop, the list should be correctly formed. One way to test this is to print out the contents of the list (using a function) on each cycle. You'd also use that function in place of the loop that follows. An interface design that I often use is:
void dump_list(FILE *fp, char const *tag, struct d_linked_list const *list)
which prints the identifying tag and the contents of the list on the given file stream. I keep such functions around for every significant data structure so that debugging is easier later.
for (q=l->first;q!=NULL;q=q->next)
This loop loses track of the space allocated to q.
printf("%d ",q->data);
You should output a newline at some point.
You should also go through the motions of releasing all the space allocated, simply to make sure you know how you could do that. When you're about to exit a program, it isn't crucial, but if you were using the list in a long-running program that needs a list once a minute, then goes off and does unrelated operations, then you'd be leaking all that memory and your long-running program would stop running after a while because it lacked the necessary memory (because it had leaked — wasted — the memory in the lists).
return 0;
}
Try moving p=(NodeT*)malloc(sizeof(NodeT)); into the top of the loop. Also, you don't need to malloc the value in q.
You never allocate space for l. Therefore, these lines are dereferencing an invalid pointer:
l->first=NULL;
l->last=NULL;
You must allocate space for l before using it:
l = malloc(sizeof(*l));
l->first=NULL;
l->last=NULL;
Also, you need to allocate a new element for each new value that you read. Thus, I would move the allocation for p into the loop:
q=(NodeT*)malloc(sizeof(NodeT));
l->first=NULL;
l->last=NULL;
while (fscanf(stdin,"%d",&d)!=EOF)
{
p=(NodeT*)malloc(sizeof(NodeT));
/* ... */
}
And you don't need to allocate space for q (you use it only for traversing the list). Finally, as pointed out in a comment, you should check if fscanf() returned 1, because only in that case you can be sure that d contains a valid value.
Putting this all together:
int main()
{
int d;
struct d_linked_list *l;
NodeT *p,*q;
if ((l = malloc(sizeof(*l))) == NULL) {
/* Handle malloc error */
}
l->first=NULL;
l->last=NULL;
while (fscanf(stdin,"%d",&d) == 1)
{
if ((p = malloc(sizeof(*p))) == NULL) {
/* Handle malloc error... */
}
p->data=d;
p->next = p->prev = NULL;
if (l->first==NULL)
{
l->first=p;
l->last=p;
}
else
{
l->last->next=p;
p->prev=l->last;
l->last=p;
}
}
for (q=l->first;q!=NULL;q=q->next)
printf("%d ",q->data);
return 0;
}
UPDATE: I changed the code to check for malloc()'s return value, and took that l->last->next = NULL; away - p->next and p->prev are now initialized to NULL inside the loop, there is no need to do it after the loop.
Related
I'm getting started with dynamic lists and i don't understand why it is necessary to use the malloc function even when declaring the first node in the main() program, the piece of code below should just print the data contained in the first node but if i don't initialize the node with the malloc function it just doesn't work:
struct node{
int data;
struct node* next;
};
void insert(int val, struct node*);
int main() {
struct node* head ;
head->data = 2;
printf("%d \n", head->data);
}
You don’t technically, but maintaining all nodes with the same memory pattern is only an advantage to you, with no real disadvantages.
Just assume that all nodes are stored in the dynamic memory.
Your “insert” procedure would be better named something like “add” or (for full functional context) “cons”, and it should return the new node:
struct node* cons(int val, struct node* next)
{
struct node* this = (struct node*)malloc( sizeof struct node );
if (!this) return next; // or some other error condition!
this->data = val;
this->next = next;
return this;
}
Building lists is now very easy:
int main()
{
struct node* xs = cons( 2, cons( 3, cons( 5, cons( 7, NULL ) ) ) );
// You now have a list of the first four prime numbers.
And it is easy to handle them.
// Let’s print them!
{
struct node* p = xs;
while (p)
{
printf( "%d ", p->data );
p = p->next;
}
printf( "\n" );
}
// Let’s get the length!
int length = 0;
{
struct node* p = xs;
while (p)
{
length += 1;
p = p->next;
}
}
printf( "xs is %d elements long.\n", length );
By the way, you should try to be as consistent as possible when naming things. You have named the node data “data” but the constructor’s argument calls it “val”. You should pick one and stick to it.
Also, it is common to:
typedef struct node node;
Now in every place except inside the definition of struct node you can just use the word node.
Oh, and I almost forgot: Don’t forget to clean up with a proper destructor.
node* destroy( node* root )
{
if (!root) return NULL;
destroy( root->next );
free( root );
return NULL;
}
And an addendum to main():
int main()
{
node* xs = ...
...
xs = destroy( xs );
}
When you declare a variable, you define the type of the variable, then it's
name and optionally you declare it's initial value.
Every type needs an specific amount of memory. For example int would be
32 bit long on a 32bit OS, 8 bit long on a 64.
A variable declared in a function is usually stored in the stack associated
with the function. When the function returns, the stack for that function is
no longer available and the variable does not longer exist.
When you need the value/object of the variable to exist even after a function
returns, then you need to allocate memory on a different part of the program,
usually the heap. That's exactly what malloc, realloc and calloc do.
Doing
struct node* head ;
head->data = 2;
is just wrong. You've declaring a pointer named head of type struct node,
but you are not assigning anything to it. So it points to an unspecified
location in memory. head->data = 2 tries to store a value at an unspecified
location and the program will most likely crash with a segfault.
In main you could do this:
int main(void)
{
struct node head;
head.data = 2;
printf("%d \n", head.data);
return 0;
}
head will be saved in the stack and will persist as long as main doesn't
return. But this is only a very small example. In a complex program where you
have many more variables, objects, etc. it's a bad idea to simply declare all
variables you need in main. So it's best that objects get created when they
are needed.
For example you could have a function that creates the object and another one
that calls create_node and uses that object.
struct node *create_node(int data)
{
struct node *head = malloc(sizeof *head);
if(head == NULL)
return NULL; // no more memory left
head->data = data;
head->next = NULL;
return head;
}
struct node *foo(void)
{
struct node *head = create_node(112);
// do somethig with head
return head;
}
Here create_node uses malloc to allocate memory for one struct node
object, initializes the object with some values and returns a pointer to that memory location.
foo calls create_node and does something with it and it returns the
object. If another function calls foo, this function will get the object.
There are also other reasons for malloc. Consider this code:
void foo(void)
{
int numbers[4] = { 1, 3, 5, 7 };
...
}
In this case you know that you will need 4 integers. But sometimes you need an
array where the number of elements is only known during runtime, for example
because it depends on some user input. For this you can also use malloc.
void foo(int size)
{
int *numbers = malloc(size * sizeof *numbers);
// now you have "size" elements
...
free(numbers); // freeing memory
}
When you use malloc, realloc, calloc, you'll need to free the memory. If
your program does not need the memory anymore, you have to use free (like in
the last example. Note that for simplicity I omitted the use of free in the
examples with struct head.
What you have invokes undefined behavior because you don't really have a node,, you have a pointer to a node that doesn't actually point to a node. Using malloc and friends creates a memory region where an actual node object can reside, and where a node pointer can point to.
In your code, struct node* head is a pointer that points to nowhere, and dereferencing it as you have done is undefined behavior (which can commonly cause a segfault). You must point head to a valid struct node before you can safely dereference it. One way is like this:
int main() {
struct node* head;
struct node myNode;
head = &myNode; // assigning the address of myNode to head, now head points somewhere
head->data = 2; // this is legal
printf("%d \n", head->data); // will print 2
}
But in the above example, myNode is a local variable, and will go out of scope as soon as the function exists (in this case main). As you say in your question, for linked lists you generally want to malloc the data so it can be used outside of the current scope.
int main() {
struct node* head = malloc(sizeof struct node);
if (head != NULL)
{
// we received a valid memory block, so we can safely dereference
// you should ALWAYS initialize/assign memory when you allocate it.
// malloc does not do this, but calloc does (initializes it to 0) if you want to use that
// you can use malloc and memset together.. in this case there's just
// two fields, so we can initialize via assignment.
head->data = 2;
head->next = NULL;
printf("%d \n", head->data);
// clean up memory when we're done using it
free(head);
}
else
{
// we were unable to obtain memory
fprintf(stderr, "Unable to allocate memory!\n");
}
return 0;
}
This is a very simple example. Normally for a linked list, you'll have insert function(s) (where the mallocing generally takes place and remove function(s) (where the freeing generally takes place. You'll at least have a head pointer that always points to the first item in the list, and for a double-linked list you'll want a tail pointer as well. There can also be print functions, deleteEntireList functions, etc. But one way or another, you must allocate space for an actual object. malloc is a way to do that so the validity of the memory persists throughout runtime of your program.
edit:
Incorrect. This absolutely applies to int and int*,, it applies to any object and pointer(s) to it. If you were to have the following:
int main() {
int* head;
*head = 2; // head uninitialized and unassigned, this is UB
printf("%d\n", *head); // UB again
return 0;
}
this is every bit of undefined behavior as you have in your OP. A pointer must point to something valid before you can dereference it. In the above code, head is uninitialized, it doesn't point to anything deterministically, and as soon as you do *head (whether to read or write), you're invoking undefined behavior. Just as with your struct node, you must do something like following to be correct:
int main() {
int myInt; // creates space for an actual int in automatic storage (most likely the stack)
int* head = &myInt; // now head points to a valid memory location, namely myInt
*head = 2; // now myInt == 2
printf("%d\n", *head); // prints 2
return 0;
}
or you can do
int main() {
int* head = malloc(sizeof int); // silly to malloc a single int, but this is for illustration purposes
if (head != NULL)
{
// space for an int was returned to us from the heap
*head = 2; // now the unnamed int that head points to is 2
printf("%d\n", *head); // prints out 2
// don't forget to clean up
free(head);
}
else
{
// handle error, print error message, etc
}
return 0;
}
These rules are true for any primitive type or data structure you're dealing with. Pointers must point to something, otherwise dereferencing them is undefined behavior, and you hope you get a segfault when that happens so you can track down the errors before your TA grades it or before the customer demo. Murphy's law dictates UB will always crash your code when it's being presented.
Statement struct node* head; defines a pointer to a node object, but not the node object itself. As you do not initialize the pointer (i.e. by letting it point to a node object created by, for example, a malloc-statement), dereferencing this pointer as you do with head->data yields undefined behaviour.
Two ways to overcome this, (1) either allocate memory dynamically - yielding an object with dynamic storage duration, or (2) define the object itself as an, for example, local variable with automatic storage duration:
(1) dynamic storage duration
int main() {
struct node* head = calloc(1, sizeof(struct node));
if (head) {
head->data = 2;
printf("%d \n", head->data);
free(head);
}
}
(2) automatic storage duration
int main() {
struct node head;
head.data = 2;
printf("%d \n", head.data);
}
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
I have a small piece of code, compiled well. But it appears segmentation fault at runtime.
#include <stdlib.h>
#include <string.h>
typedef struct ListElmt_ // Define a structure for linked list elements.
{
void *data;
struct ListElmt_ *next;
} ListElmt;
typedef struct List_ //define a structure for linked lists.
{
int size; // the size of the linked list
ListElmt *head; // the head element
ListElmt *tail; // the tail elemtent
} List;
void list_init(List *l)
{
l->size = 0;
l->head = NULL;
l->tail = NULL;
}
int main()
{
List *ls = NULL;
list_init(ls);
return 0;
}
I have tried but could not find out what's wrong. Please help? I am a newbie, could anyone suggest me tools to find this kind of error?
Your failing line is:
l->size = 0;
Since you initialized ls to NULL the above line is doing NULL->size, i.e. an illegal dereference. You need to allocate memory for ls first.
However, there is no reason for a dynamic allocated List. Simply do:
int main()
{
List ls; // Don't make list a pointer - just an ordinary var
list_init(&ls); // Pass the address of ls (i.e. &ls) as the function
// expects a pointer.
return 0;
}
To find the kind of problem, you had with the pointer version, you could use a debugger and use single-step, i.e. execute the code line-by-line until you hit the failing point. Another way is to insert a number of printf statements so that you can see what the code did just before crashing.
The variable ls should be provided memory location before any access.
Use: ls = malloc(sizeof(List)); before use of ls.
A segmentation fault usually appears when trying to access a memory location which does not exist yet.
So I'm doing some linked list revison and Im trying to just load a list with some numbers and then print it out. Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct stack {
int data;
struct stack *next;
}*stack;
stack create_s(void){
stack s = (void*)malloc(sizeof(stack));
s->next = NULL;
return s;
}
void push_s(stack s, int data) {
while (s->next != NULL) {
s = s->next;
}
s->next = (void*)malloc(sizeof(stack));
s=s->next;
s->data = data;
s->next = NULL;
}
void print_s(stack s) {
if (s==NULL) {
return;
}
else {
while (s->next != NULL) {
printf("%d\n",s->data);
s=s->next;
}
}
}
int main (void) {
stack s = create_s();
push_s(s,2);
push_s(s,4);
push_s(s,6);
push_s(s,8);
print_s(s);
return 0;
}
My output is however:
-1853045587
2
4
6
when it should be
2
4
6
8
Is it printing the address of my struct at the beginning? Also, why is it not printing my last element?
Thanks
The code contains several errors, but the first thing that catches the eye is that your memory allocation is already obviously broken
stack s = (void*)malloc(sizeof(stack));
You defined stack as a pointer type. This means that sizeof(stack) evaluates to pointer size and the above malloc allocates enough space to store a single pointer, not enough for the entire struct stack object. The same memory allocation error is present in push_s as well.
Here's some advice
Don't hide pointer types behind typedef names. Define your stack as
typedef struct stack{
int data;
struct stack *next;
} stack;
and use stack * wherever you need a pointer. I.e. make that * visible instead of hiding it "inside" a typedef name. This will make your code easier to read.
Don't cast the result of malloc. Anyway, what is the point of casting it to void * when it is void * already???
Don't use sizeof with types unless you really really have to. Prefer to use sizeof with expressions. Learn to use the following malloc idiom
T *p = malloc(sizeof *p);
or, in your case
struct stack *s = malloc(sizeof *s);
This will allocate a memory block of appropriate size.
Also, as #WhozCraig noted in the comments, the very first node in your list is apparently supposed to serve as a "sentinel" head node (with undefined data value). In your code you never initialize the data value in that head node. Yet in your print_s function you attempt to print data value from the head node. No wonder you get garbage (-1853045587) as the first line in your output. Don't print the very first node. Skip it, if it really is supposed to serve as a sentinel.
Also, the cycle termination condition in print_s looks strange
while (s->next != NULL)
Why are you checking s->next for NULL instead of checking s itself? This condition will terminate the cycle prematurely, without attempting to print the very last node in the list. This is the reason why you don't see the last element (8) in your output.
The actual cause of the given output can be fixed by changing:
s=s->next;
s->data = data;
to
s->data = data;
s=s->next;
I tried to sort directly the numbers I enter in a linked list using two functions the first one add the element at the head the second one which contain the segmentation fault is supposed to exploit the first one to do the job.
#include <stdio.h>
#include <stdlib.h>
typedef struct cellule
{
int val;
struct cellule *suivant;
} cellule;
typedef struct cellule* liste;
liste insert_tete(liste L,int n)
{
liste p;
p=malloc(sizeof(cellule));
p->val=n;
p->suivant=L;
return p;
}//ok :)
liste insert_croissant(liste L,int n)
{
if(!L)
{
L=insert_tete(L,n);
return L;
}
liste p,q;
for(q=L,p=L; (p!=NULL )&&(n> (p->val)) ; q=p,p=p->suivant); //
p=insert_tete(p,n);
q->suivant=p;
return L;
}
By no means do I believe this will fix it, but there is at least one bug in your code.
Consider the case where L is initialized, but n < L->val:
// p = L, q = L;
// Let L = [val|->...
p=insert_tete(p,n);
// p = [n|->[val|->...
q->suivant=p;
// q = L
// Therefore [val|->[n|->L
// And you've just made your linked list circular.
liste insert_croissant(liste L,int n)
{
if(!L)
{
L=insert_tete(L,n);
return L;
}
Here we know that L is not NULL
liste p,q;
for(q=L,p=L; (p!=NULL )&&(n> (p->val)) ; q=p,p=p->suivant); //
The only way to get a legitimate segfault here is that one of the pointers p follows is a non-0 pointer that doesn't point to a properly allocated struct cellule, but to some inaccessible memory. Then trying to access p->val (or p->suivant) causes a segfault.
The most common way (in my limited experience) to get into that situation is forgetting to initialise the first pointer to 0.
The code has a problem where the list can get corrupted in certain cases; it's easy to get the list into a state where it's not properly terminated (and possibly 'lose' nodes from the list). And that situation could cause problems depending on how other code might manipulate the list.
If you try to add a new node on a list that isn't empty, but the new value is less than or equal to the first node's value, the list will end up being a circular list with two nodes on it. Any nodes after the one that was at the head of the list are lost.
This happens because in that case both p and q will point to that node when insert_tete(p,n) is called. After insert_tete(p,n) returns, p-suivant and q will be pointing to the node at the head of the list. so when
q->suivant = p;
is executed, the list will be circular and 'extra' nodes will be lost.
Depending on how your other operations act on the list, (especially if/how you delete elements) you could find yourself with a dangling pointer left in a suivant field (which may cause a segfault), or end up in an infinite loop.
Simplified version using pointer-to-pointer. Note: there is no special case for the empty list.
struct cellule {
int val;
struct cellule *suivant;
};
struct cellule *insert_croissant(struct cellule **LL, int val)
{
struct cellule *p,**pp;
for(pp=LL ; *pp && (*pp)->val < val ; pp = &(*pp)->suivant) {;}
/* When we arrive here, pp points to whatever pointer happens
** to point to our current node.
** - If the list was empty, *pp==NULL
** - if the place to insert happens to be the tail of the list, *p is also NULL
** - in all cases, *pp should be placed after the new node, and the new node's pointer should be assigned to *pp
*/
p = malloc(sizeof *p);
p->val = val;
p->suivant = *pp;
*pp = p;
return *LL;
}