how to correctly initialize a LinkList - c

When initializing a linked list, I define parameter as *L, like:
Status InitList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(struct LNode));
if(!*L)
exit(OVERFLOW);
(*L)->next=NULL;
return OK;
}
but not
Status InitList(LinkList L)
{
L=(LinkList)malloc(sizeof(struct LNode));
if(!L)
exit(OVERFLOW);
(L)->next=NULL;
return OK;
}
Why it cannot be true?
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList;

In the second implementation, you have a local variable L that you initialize. The trouble is, it is a local variable — changing it does not change the variable in the calling code. When the function exits, you've lost the memory that was allocated — a memory leak. They're bad!
The first code gets a pointer to the variable in the calling code and carefully changes it. This does not leak memory.
You can modify the second so it works by using code like this:
LinkList NewList(void)
{
LinkList L = (LinkList)malloc(sizeof(*L));
if (L)
{
L->data = 0;
L->next = NULL;
}
return L;
}
It does a different job, so it was renamed.
Note that it ensures all elements of the structure are initialized to known values. You'd call it like this:
LinkList list = NewList();

Related

C structure containing references to another structure

I'm learning C and trying to create dynamic double ended queue. I need to have one structure element that contains references to queue's front and end (head, tail of type node) and I'm trying to pass this element to a function and allocate memory for head and tail node. And i get segmentation fault.
My structures
struct node_st {
struct node_st* prev_node;
struct node_st* next_node;
// Value type can be changed.
int value;
bool is_zero_element;
};
typedef struct node_st node;
struct deque_link {
struct node_st* head;
struct node_st* tail;
int errorcode;
};
typedef struct deque_link dlink;
Main function
#include "deque.h"
#include <stdio.h>
int main() {
dlink* deque;
deque_create(deque);
}
deque_create() function
void deque_create(dlink* deque) {
deque->head = deque->tail = (node*)malloc(sizeof(node));
}
I guess I don't understand pointers enough, but I will be very happy if someone could help.
The pointer deque that you pass to deque_create is not initialized. It has indeterminate ("garbage") content. Therefore, it does not point to a valid deque. But you try to access it with the -> operator.
Your initialization / creation of the deque is on the wrong level: You try to create nodes, but you should create a deque (without any nodes, initally.)
You could write a constructor function that allocates memory and initializes it:
dlink *deque_create(void)
{
dlink *deque = malloc(sizeof(*deque));
// Handle allocation failure
deque->head = deque->tail = NULL;
deque->errorcode = 0;
return deque;
}
Then use it like this:
dlink* deque = deque_create();
// do stuff with deque
// delete deque and its nodes
You should also write a destructor function which deletes all nodes to complement the constructor.

copying a struct in a function and returning the copy in c

I am implementing a queue using a generic linked list in C where each node in list is a simple struct which contains a void pointer and a node pointer to the next node. In the dequeue operation I want to remove the head (which is working fine), but I also want to return that node after it is removed.
EDITED TO CLARIFY
What i did in the dequeue function is (example):
//This is my queue struct
typedef struct Queue{
LinkedList* list;
size_t item_size;
} Queue;
//this is the dequeue function
Node* dequeue(Queue* queue){
Node* head = queue->list->head;
Node* returnedValue = (Node*)malloc(sizeof(Node));
memcpy(returnedValue, head, sizeof(Node));
removeBegin(queue->list);
return returnedValue;
}
//this is the remove head function
void removeBegin(LinkedList* list){
Node* tempHead = list->head;
list->head = list->head->next;
tempHead->next = NULL;
free(tempHead->value);
tempHead->value = NULL;
free(tempHead);
tempHead = NULL;
}
the problem is everything before the free function is ok. Everything is being copied correctly. But immediately after the free function call the value that is copied to the newly allocated node becomes garbage (or 0).
The way I call the function is simply initialize the queue using this function:
Queue* init_queue(size_t size){
Queue* queue = (Queue*)malloc(sizeof(Queue));
// int x = 10;
queue->list = createList(NULL, size);
return queue;
}
then call dequeue and pass it the pointer of the queue.
How can I solve this?
thanks a lot.
The memory allocating using
Node* n1 = (Node*)malloc(sizeof(Node));
is uninitialised. This means that accessing the value of n1->value gives undefined behaviour. A consequence is that
memcpy(n1->value, n->value, sizeof(n->value));
also gives undefined behaviour.
When behaviour is undefined, the consequences of executing any further code could be anything. Your observation
newly allocated node becomes garbage (or 0)
is one possible outcome.
There are more problems as well. However, you haven't provided enough information (e.g. how is the function called? how is the pointer passed as n initialised? how is n->value initialised?) so it is not possible to give advice on how to FIX your function.

Doubly linked list does not create properly

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.

Making Multiple Stacks

I wanted to make an array of stacks in C, where I should be able to retain individual stacks and their respective information. I currently have the following implementation, which only works for one stack. How can I modify the functions push and pop to achieve multiple stacks each using the same function.
(I was easily able to do this in Java, as I could create a class, but I have no idea in C)
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *first = NULL;
void push(int x) {
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = first;
first = newnode;
}
int pop() {
int temp = first->data;
first = first->next;
return temp;
}
You have a memory leak in your code in the pop() function. You should free the memory that you have malloc'd.
Taking advice from #Jongware's comments below your question.
Here's a new version of the push() and pop() functions.
#include <stdlib.h>
struct node {
int data;
struct node *prev;
};
void push(struct node **stack, int x) {
if (stack != NULL)
{
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->prev = *stack;
*stack = newnode;
} else
{
// You didn't give me a valid pointer to a stack, so I'm ignoring you!
}
}
int pop(struct node **stack) {
int temp = 0; // This is the default value that is returned when there is an error.
struct node *oldnode;
if (stack != NULL)
{
if (*stack != NULL)
{
oldnode= *stack;
temp = oldnode->data;
(*stack) = oldnode->prev;
free(oldnode);
} else
{
// The stack is empty. I will just ignore you and return the default value for temp.
}
} else
{
// You didn't give me a valid pointer to a stack so I'm ignoring you and returning the default value of 0 for temp!
}
return temp;
}
And here's an example of how to use them:
#include <stdio.h>
int main()
{
struct node *stack1 = NULL, *stack2 = NULL;
int value;
// Push some values onto the stacks
printf("Pushing 7 and then 8 onto stack1\n");
push(&stack1, 7);
push(&stack1, 8);
printf("Pushing 3 onto stack2\n");
push(&stack2, 3);
// Pop and print both stacks
value = pop(&stack2);
printf("Popped %d from stack2\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
return 0;
}
As for where you should be declaring your stack pointers that is really up to you and how you intend to use them.
Have a read about C variable scope for some options and how you might use them.
Also, I will have to include a warning with declaring these pointers inside functions. In whichever function you declare your pointer you must make sure that you pop everything off the stack before you exit the function, otherwise you will lose the pointer and leak all the allocated memory. If this is not what you want, or you want the pointer to outlive the function then you can declare the pointer globally or pass it around, making sure that everything is popped off the stack before your program exists or loses the pointer.
Another thing that you might want to consider is what happens when you use pop() on an empty stack? The implementation that I have given you simply returns 0 and ignores you. You might want to handle that a little better.
You can only have one stack because you defined it as a global variable:
struct node *first = NULL;
In Java you would have used a class. In C, you can likewise do "object based" programming by defining an abstract data type which holds your instance variables, instead of using global variables:
struct stack {
struct node *first;
};
there are no class features like constructors or destructors, so you write functions to initialize a stack, destroy a stack and so forth. To achieve multiple instantiation, you explicitly pass a stack * argument to each function in the stack module.
You might want to name your functions in some consistent way, like stack_init, stack_cleanup, stack_push and so on.
There are design questions to settle such as: does the caller allocate struct stack, for which you provide stack_init function? Or do you provide a one-step stack_alloc function that allocates and returns a stack? Or perhaps both, so the user can choose performance or convenience?
void stack_init(struct stack *);
void stack_cleanup(struct stack *);
struct stack *stack_alloc(void); /* also calls stack_init on new stack */
void stack_free(struct stack *); /* calls stack_cleanup, then frees */
It's possible to do information hiding in C, whereby you can completely conceal from the client code (which uses the stack module) what a struct stack is.
However, if you provide a stack_init, then the client has to know how large a stack is, since it provides the memory for it. Generally, modules which completely hide an implementation also hide how large it is, and so provide only a stack_alloc and stack_free type interface.
An advantage of that is that client code doesn't have to be recompiled if the stack module is changed and the structure is larger. This is very good if you're writing a widely-used library: it is easy for users to upgrade or possibly downgrade.
However, revealing the implementation allows for more efficient code, since the client has the freedom to choose memory management for stacks. Stacks can be declared as local variables in automatic storage ("on the stack", so to speak), statically as global variables, or packed into arrays.
The user can do things like:
{
struct stack temp_stack;
stack_init(&temp_stack); /* stack is good to go! */
/* ... use stack ... */
stack_cleanup(&temp_stack); /* don't forget to clean up */
}
and things like:
struct stack array_of_stacks[42];
int i;
for (i = 0; i < 42; i++)
stack_init(&array_of_stacks[i]); /* no memory allocation taking place */
All this code has a compile-time dependency of the definition of struct stack; whenever struct stack is touched, it must be recompiled.
Note that if the above struct stack definition is the exact definition for a stack (the only property of a stack is that it has a pointer to a top node which can be null) then, physically speaking, a struct stack * pointer is actually a pointer to a pointer. We can use a typedef name to write the code so that we can use either definition:
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
Either way, the API in terms of stack_t then looks like this:
void stack_init(stack *s);
int stack_push(stack *s, int item);
or whatever. If stack is a pointer (alternative "A" above) then stack *s is a pointer-to-pointer, and so your code will be full of pointer-to-pointer manipulation.
If you're not comfortable with pointer-to-pointer syntax all over the place, then you can give yourself a macro to pretend that it's a structure anyway.
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
#define stack_top(s) (*(s)) /* dereference stack s to obtain the top pointer */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
#define stack_top(s) ((s)->top) /* dereference struct pointer to get top pointer */
In the code you can then do things like:
/* push new_node onto stack */
new_node->next = stack_top(s);
stack_top(s) = new_node;
If you consistently use the stack_top accessor, you can now flip the representation of the stack type between alternative "A" and "B" without rewriting any of your code (only recompiling it).
Some nit-picky C programmers will cringe at stack_top(s) = new_node since it looks like a function call is being assigned (which is impossible in C without using macros to bend the language), and prefer a "setter" function for that stack_top_set(s, new_node). That's mostly just outdated, parochial thinking.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int Item;
#define ItemFormat "%d"
struct node {
Item data;
struct node *next;
};
typedef struct node *Stack;
void push(Stack *st, Item x){
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = *st;
*st = newnode;
}
bool isEmpty(Stack st){
return st == NULL;
}
Item pop(Stack *st) {
if(!isEmpty(*st)){
struct node *p = *st;
Item value = p->data;
*st = p->next;
free(p);
return value;
}
fprintf(stderr, "Stack is Empty!\n");
return (Item)0;
}
bool inputItem(Item *x){
int stat;
if(1==(stat=scanf(ItemFormat, x)))
return true;
if(stat == EOF)
return false;
scanf("%*[^\n]");
return false;
}
void printItem(Item x){
printf(ItemFormat, x);
}
int main(void){
Stack st = NULL, array[5] = { NULL };
Item x;
while(inputItem(&x)){
push(&array[1], x);
}
while(!isEmpty(array[1])){
x = pop(&array[1]);
printItem(x);
printf("\n");
}
/*
while(inputItem(&x)){
push(&st, x);
}
while(!isEmpty(st)){
x = pop(&st);
printItem(x);
printf("\n");
}
*/
return 0;
}
The static implemetation of two stacks in a single array in C looks something like this...the stack structure will have two top variables top1 and top2.
struct stack
{
int data[MAX];
int top1,top2;
}s;
top1 is initialized to -1 while top2 is initialized to MAX
Overflow condtitions:
1]
if((s->top1)+1==s->top2)
printf("Stack 1 overflow\n");
2]
if((s->top2)-1==s->top1)
printf("Stack 2 overflow\n");
The underflow conditions become pretty obvious. This method may not be memory efficient since we might run out of storage space in the array but it is the basic fundamentals of multiple stacks in a single array.

Linked List in C error -- Invalid Initalizer error

I am attempting to create a Linked List using C (NOT C++). The Linked List is initialized through the function llinit() which should return a list struct. However, when I compile the code I get an error stating "error: invalid initializer" in the lltester.c file. Why is this?
This is the function used to initialize the linked list in my llist.c file:
list llinit()
{
list* ll = malloc(sizeof(list));
ll->head = NULL;
ll->tail = NULL;
return *ll;
}
This is the list struct in my llist.h file:
typedef struct {
node *head;
node *tail;
} list;
This is my main function in my lltester.c file where I attempt to initialize the list:
int main()
{
list myList= llinit(); //This is the line where the error occurs on!
return 0;
}
Your code is leaking memory, since it's allocating the list with malloc() then returning that structure's content by value.
if you want to have a function that returns an empty list by value, you should do just that:
list llinit()
{
list ll;
ll.head = NULL;
ll.tail = NULL;
return ll;
}
The above is just fine, there's no risk of the value "disappearing" due to it going out of scope, this is just as safe as e.g. a function returning a local int value. The return value (all of it!) is copied to the caller's memory as needed.
It's then trivial for the caller to decide whether or not the node should be on the heap or not.
UPDATE: Here is the code on ideone, it really does compile and does not generate an error for the assignment in main().
you have to declare the structure as
typedef struct _list{
list* head; /* could have been struct node* as well */
list* tail;
} list;
Also the list is your custom struture. And the llPushBack() is not a bember of your structure.

Resources