I was trying to implement circular queue functionality. I am a C++ coder and I found it surprising that in C, struct cannot have member functions. Anyway this is my implementation:-
#include <stdio.h>
#include <stdlib.h>
struct node
{
int nvalue;
struct node *next;
};
struct CLlist
{
struct node* head;
struct node* tail;
int size;
};
void insert(struct CLlist *l,int num)
{
struct node *n=malloc(sizeof(struct node));
n->nvalue=num;
n->next=NULL;
if((l->head==l->tail)==NULL)
{
l->head=l->tail=n;
}
else if(l->head==l->tail && l->head!=NULL)
{
l->head->next=n;
l->tail=n;
l->tail->next=l->head;
}
else
{
l->tail->next=n;
l->tail=n;
l->tail->next=l->head;
}
l->size++;
}
void print(struct CLlist *l)
{
int idno=1;
printf("printing the linked list with size as %d\n",l->size);
struct node *cptr;
for(cptr=(l->head);cptr!=(l->tail);cptr=cptr->next)
{
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
idno++;
}
//this is to print the last node in circular list : the tail node
idno++;
cptr=cptr->next;
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
}
int main()
{
struct CLlist a;
struct CLlist *l;
l=&a;
insert(l,2);
insert(l,5);
insert(l,7);
insert(l,10);
insert(l,12);
print(l);
return 0;
}
I get segmentation fault in the line
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
why does the error occur? I guess I am not passing l by pointer by value (passing pointers as by value) properly. could somebody help me in pointing out where I am going wrong?
Thanks
You never initialize the variable a in the main function, so its contents is indeterminate and using the members of that structure will lead to undefined behavior.
Your code has two issues, the first one more serious.
Your first issue is that the head and tail members of your CLlist structure are not being initialized to NULL, which can (non-deterministically) keep any real data from being stored in your structure. This can be fixed by adding the following 2 lines in main just before the first insert call:
l->head = NULL;
l->tail = NULL;
Your second problem is in this line:
if((l->head==l->tail)==NULL)
While it looks like this is comparing both l->head and l->tail to NULL, it's actually comparing l->head to l->tail, and then comparing that boolean result to NULL, which is effectively 0. The line should be changed to:
if((l->head == NULL) && (l->tail == NULL))
This will individually test both the head and tail pointers, and will only take that branch if they are both NULL.
You have a pointer
struct node *cptr;
// You're probably trying to access an unassigned pointer head in the next step
for(cptr=(l->head);cptr!=(l->tail);cptr=cptr->next)
As per the standards, there is no requirement that
a->head & a->tail are initialized to NULL
when you did
struct CLlist a;
Standard ISO/IEC 9899:201x clause 6.7.9->10 states
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate.
In fact you're:
struct CLlist a;
// missing something here.
struct CLlist *l;
l=&a;
Related
I am writing a code to create a linked list using structures in C language.
I have defined the structure with a data type and a pointer to structure type. Further I have used typedef to typecast this to Node_s.
I am using a function to initialise the first node; which basically won't contain any value but just returns the headpointer, which I will use to point to my next structure (node).
In the main block, I am initialising a structure pointer with Null value and then feeding the value from initialiser function to this pointer.
But this code is returning zsh: segmentation fault . Can someone explain me the issue!
#include <stdio.h>
#include <stdlib.h>
//Node* Initialize;
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s* Initialize(){
Node_s init_node;
Node_s* headlist;
init_node.data = 0;
init_node.next = headlist;
return headlist;
}
int main()
{
Node_s* ptr = NULL;
ptr = Initialize();
// 1st Node
ptr->data = 1;
Node_s* ptr2 = NULL;
ptr->next = ptr2;
// 2nd Node
ptr2->data = 1;
ptr2->next = NULL;
printf(" \n done deal %d", (*ptr2).data );
return 0;
}
main(): the variable ptr is uninitialized as returned from Initialize(). If it points to NULL or any other memory you don't have access to it will segfault when you deference it's members (ptr->data).
main(): the variable ptr2 is initialized to NULL, then you try to dereference it set its members. This will trigger a segfault if you get there.
Initialize(): init_node is a local variable and has no effect outside the function.
Initialize(): headlist is uninitialized as I mentioned above.
Initialize(): I suggest you change the signature to Node_s *Initialize(int data) so you can set the data to the value you need instead of a dummy value.
Here's a better starting point:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s *Initialize(int data) {
Node_s *headlist = malloc(sizeof(*headlist));
if(!headlist) {
printf("malloc failed\n");
return NULL;
}
headlist->data = data;
headlist->next = NULL;
printf("done deal %d\n", headlist->data);
return headlist;
}
int main() {
Node_s *ptr = Initialize(1);
if(!ptr)
return 1;
ptr->next = Initialize(2);
if(!ptr->next)
return 1
return 0;
}
The next step would be to eliminate the printf("done deal ...) statement in favor of a function that prints your linked list. Then write a function that frees the linked list. Then write a function that can Append(int data) an element to your list to replace Initialize().
I try to create a library program with a linked list in C. I get an "assignment makes integer from pointer without a cast" error and when I try to print screen the list print_list function not working; only printf "H->" doesn't print in the while loop.
#include<stdio.h>
#include<stdlib.h>
struct node
{
char bookname[40];
char writer[50];
int available;
int memberid;
struct node *next;
};
void AddBook(struct node **head, char bookname[50], char writer[50], int available, int memberid)
{
struct node * new_node = NULL;
struct node * last = NULL;
new_node = (struct node *)malloc(sizeof(struct node));
if (new_node == NULL)
{
printf("Failed to insert element. Out of memory");
return;
}
new_node->bookname[50]= bookname;
new_node->writer[50]= writer;
new_node->available= available;
new_node->memberid= memberid;
new_node->next = NULL;
At this point, I get an "assignment makes integer from pointer without a cast" problem on these two;
new_node->bookname[50]= bookname;
new_node->writer[50]= writer;
if( *head == NULL)
{
*head = new_node;
return;
}
last = *head;
while(last->next) last = last->next;
last->next = new_node;
}
void print_list(struct node *head)
{
printf("H->");
while(head)
{
printf("%s %s %d %d ->", head->bookname[50],head->writer[50],head->available,head->memberid);
head = head->next;
}
printf("|||\n\n");
}
int main()
{
struct node * head = NULL;
AddBook(&head,"Hamlet","William_Shakespeare",1,1);
AddBook(&head,"The Odyssey","Homer",1,1);
AddBook(&head,"The Great Gatsby","F. Scott Fitzgerald",1,1);
print_list(head);
return 0;
}
What can I do to get book name and writer get with scanf? I tried to do it this way but it didn't work;
int main()
{
struct node * head = NULL;
struct node book;
prinft("please enter the bookname:");
scanf("%s", book.bookname);
prinft("\n please enter the writer name:"); scanf("%s",book.bookname);
book.available=1;
book.memberid=1;
AddBook(&head,*book.bookname,*book.writer,book.available,book.memberid);
print_list(head);
return 0;
}
On these lines:
new_node->bookname[50]= bookname;
new_node->writer[50]= writer;
You think you're copying the contents of one array to another. What you're actually doing is attempting to copy a pointer (since arrays as function arguments decay to pointers) to a single element of the array (i.e. a char), and to an element past the end of the array at that.
Even if you removed the index from the destination, this wouldn't work because arrays are not assignable.
To copy one string to another, use strcpy:
strcpy(new_node->bookname, bookname);
strcpy(new_node->writer, writer);
Although arrays and pointers to arrays can be treated as interchangeable in some cases, this is not one of them. Since bookname and writer are declared as char arrays and not char pointers, you won't be able to accomplish what you're trying to do by assigning a char * to either of them. Instead, you should use strncpy() (assuming these are null-terminated strings) to copy them over.
You should also double-check the array indices--you're trying to copy to bookname[50] (which would be the 51st element, because of zero-based numbering) while bookname[]'s declaration is only for 40 elements (for the same reason of zero-based index numbering, there is no writer[50] even though it is declared as char writer[50] -- the declaration creates a 50-element array, whose first element is at index 0 and fiftieth at 49).
I've started implementing a circular queue in C, and I have the following lines of code:
#include <stdio.h>
#include <stdlib.h>
#include "cirq.h"
//allocate a circular queue
cirq cq_alloc(void){
cirq cq = NULL;
element *head;
element *tail;
if((head = malloc(sizeof(struct element*))) &&
(tail = malloc(sizeof(struct element *)))){
head->content = 0; // head node keeps track of size.
tail->content = NULL;
head->next = tail;
tail->next = head;
cq = &head;
} else {
printf("ERROR: No space for more cqueues.\n");
}
return cq;
}
int cq_size(cirq q){
return (int)(*q)->content;
}
int main(){
cirq q = cq_alloc();
printf("Size of element ptr %lu\n", sizeof(struct element *));
printf("%d\n", cq_size(q));
return 0;
}
Now when I compile and run this program, having commented out the line in main that prints out sizeof(struct element *)), the program runs fine and I get the right size of the queue, 0. When I leave the line in, the size of the struct is printed out, but after that I get a segmentation fault: 11. Also, to make things clear, the struct element has void *data and struct element *next fields. How can adding in a line that prints stuff change the behavior of the program so much?
EDIT: cirq.h
#ifndef CIRQ_H
#define CIRQ_H
typedef struct element **cirq; // cirq handle
typedef struct element {
void *content;
struct element *next;
} element;
extern cirq cq_alloc(void);// allocate a queue
extern int cq_size(cirq q);// return the size of a queue
extern void cq_enq(cirq q, void *value);// add a value to the queue
extern void *cq_deq(cirq q);// dequeue and return a queue value
extern void *cq_peek(cirq q);// return the value at the queue head
extern void cq_rot(cirq q);// requeue the head element at the tail
extern void cq_free(cirq q);// return all space allocated to queue
#endif
This is a bad smell:
if((head = malloc(sizeof(struct element*))) &&
You're mallocing the size of a pointer. I think you meant to malloc the struct itself...?
It doesn't really matter what cirq is, the fact that you return the address of a local object is the problem.
This here
cq = &head;
is causing the undefined behavior, because that's the address of the pointer head which is stored locally in the function only, when the function returns it's deallocated and thus invalid. Using it elsewhere (outside the function) is Undefined Behavior.
Also, do not typedef a pointer. Never do that, let the code reader know that it is a pointer.
I am studying the following C code:
typedef struct msg *m_;
struct msg
{
long from;
long to;
m_ link;
};
m_ queue;
I would like to see an example that explains the role of the pointer, i.e. m_, of the structure inside the structure itself m_ link!
Thank you very much.
To be pedantic: link is a pointer. m_ is not a pointer, it's a typedef. It is used to avoid the need to say "struct msg* link;" inside the struct definition.
As answered in the comment above, the queue is represented by a pointer to the first item, which has a pointer to the second (if any), and so on until you reach a NULL pointer.
It's important to take care when building such lists that no node points to itself or to any precursor, or you get an infinite loop chasing to the tail.
Pointers to the structure type inside the structure itself are very often used for linked lists, trees, etc. In your example, it is referring to a queue implementation.
Here is a very minimal example of a stack implementation using a linked list. The functions require the address of a stack pointer, and an empty stack is a NULL pointer.
struct linked_stack
{
int data;
struct linked_stack *next;
};
void linked_stack_push(linked_stack **stck, int data)
{
struct linked_stack *node = malloc(sizeof(struct linked_stack));
if (node != NULL)
{
node->data = data;
node->next = *stck;
}
*stck = node;
}
int linked_stack_top(linked_stack **stck)
{
if (*stck != NULL)
return (*stck)->data;
return 0; /* stack is empty */
}
void linked_stack_pop(linked_stack **stck)
{
struct linked_stack *node = *stck;
if (*stck != NULL)
{
*stck = node->next;
free(node);
}
}
Example usage:
int main(void)
{
struct linked_stack *stack = NULL;
linked_stack_push(&stack, 10);
printf("top of stack = %d\n", linked_stack_top(&stack));
linked_stack_pop(&stack);
return 0;
}
In a program I'm writing I need a linked list, so it's a pretty specific implementation. It needs:
the ability to add a node to the end
the ability to remove a node whose data matches a specified value
The data is a cstring, no more than 20 characters in length. I'm not very experienced with C and am getting errors with the following signature void addToEnd(llist root, char entery[51]). I tried replacing llist with node but then the error is "unknown type name node". How can I get rid of this?
Here's the code
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct node
{
char entery[51];
struct node* next;
} llist;
/*may be losing root address permanently*/
void addToEnd(llist root, char entery[51])
{
while(root->next != NULL)
root = root->next;
node last = malloc(sizeof(struct node));
root->next = last;
strcpy(last, entery);
}
int main()
{
struct node *root = malloc(sizeof(struct node));
root->next = NULL;
strcpy(root->entery, "Hello");
struct node *conductor = root;//points to a node while traversing the list
if(conductor != 0)
while(conductor->next != 0)
conductor = conductor->next;
/* Creates a node at the end of the list */
conductor->next = malloc(sizeof(struct node));
conductor = conductor->next;
if (conductor == NULL)
{
printf( "Out of memory" );
return EXIT_SUCCESS;
}
/* initialize the new memory */
conductor->next = NULL;
strcpy(conductor->entery, " world\n");
addToEnd(root, " at the");
addToEnd(root, " end");
/*print everything in list*/
conductor = root;
if(conductor != NULL)
{
while(conductor->next != NULL)
{
printf("%s", conductor->entery);
conductor = conductor->next;
}
printf("%s", conductor->entery);
}
return EXIT_SUCCESS;
}
One thing I'm unclear about, is in all the examples I've seen is they typedef the struct. Why? Let me elaborate: how do you know if you want to be passing just node or struct node. Also I don't really see the point, struct node isn't that much longer than a single typedef'd name.
Problems:
line 12: void addToEnd(llist root, char entery[51]) shall be void addToEnd(llist *root, char entery[51]). Here root must be a pointer type or you actually can not modify its value inside the function and make it visible outside the function.
line 16: node last = malloc(sizeof(struct node)); shall be struct node *last = malloc(sizeof(struct node));. Since in C you must reference a type name with the keyword struct, and also it shall be a pointer or it cannot be initialized with malloc.
As for your typedef question, I believe it is optional and people use it only for convenience. Personally I don't use typedef on a struct very often.
EDITED:
Also your code comes with bugs. Sorry I was only focusing on the syntax before.
Please notice that malloc in C don't assure you that the allocated memory is zeored, it's actually could be anything inside. So you need to fill it manually: to add a line last->next = NULL; at the end of addToEnd.
To refer to your struct of the linked list, use struct node, after the typedef, you can also use llist. You can also ues, as the linked question uses.
typedef struct node
{
char entery[51];
struct node* next;
} node;
In this style, you can use node the same as struct node.
The syntax error you are facing is, you misused the arrow operator ->, it's used with pointers of struct. For struct, use the dot operator .
So for the function
void addToEnd(llist root, char entery[51])
{
while(root->next != NULL)
root = root->next;
You should pass in a pointer:
void addToEnd(llist* root, char entery[51])