Initialize a linked list using ints in C - c

I need to initialize a linked list using ints given from the main.c.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char ** argv)
{
int b = 128;
int M = b * 11; // so we have space for 11 items
char buf [1024];
memset (buf, 1, 1024); // set each byte to 1
char * msg = "a sample message";
Init (M,b); // initialize
I know what I have isn't correct, but it's the best I could come up with.
#include <stdio.h>
#include "linked_list.h"
struct node
{
int value;
struct node *next;
};
struct node* head;
struct node* tail;
void Init (int M, int b)
{
head = (struct node *) malloc(sizeof *head);
tail = (struct node *) malloc(sizeof *tail);
head->next = tail;
tail->next = tail;
}
I just cannot see how to initialize the linked list using the ints. Thank you.

Your list is described by a pointer to its head element.
Now you want to initialise the list so that it is usable. The default state is an empty list, i.e. one that does not have any nodes. So what you don't do is to allocate memory. Just do this:
struct node *head = NULL;
You have a NULL head, which means that you don't have any elements. When you add nodes, you create them with malloc and assign them via this pointer. If the head is NULL, it must be updated to point to the first node, whose next member must be NULL.
Remember: Most pointers just point to existing data. There's no need to allocate memory to such pointers. And make sure to always initialise pointers properly; they should either point to valid memory or be NULL to mean "not pointing to anything".

Related

Can I malloc only the exact memory needed for an input string and point it?

I'm making a program where I save input strings from fgets in a list, they have a fixed maximum lenght but can also be shorter; i save them like this:
typedef char line[LINE_SIZE];
struct node{
line *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
but, in my program I just do malloc(sizeof(line)) which is an array with the maximum fixed lenght.
My question is, if I were to allocate something like malloc( strlen( str ) + sizeof( ( char )'\0' ) ) to precisely use only the memory needed, how can I point it?
Is it okay using a char* inside the node struct? Do I risk something?
I have heard about flexible arrays inside the structs but I don't want to put the array directly inside the struct, because for the program I need to be able to detach it and then point to it with another pointer
malloc() returns the address it allocated, you can assign the return value to a variable and point it. You don't need to always allocate maximum or the same size of memory even though the variable is the same member of a struct.
char* line=malloc(strlen(str)+1); // +1 for null terminate
strcpy(line, "This is a str"); // points the memory of returned
Using a char* in a struct is absolutely fine. Please treat a member of struct like a plain variable.
struct node
{
char* t;
struct node* prev;
struct node* next;
}
node n;
n.t = malloc(strlen(str) + 1); // it's fine.
strcpy(n.t, "This is a node"); // using the memory you allocated above
n.prev = n.next = NULL;
... // doing some processing
free(n.t); // don't forget to call free() when you're done using the memory.
For your purpose, you must allocate the node structure and the line fragment separately.
Depending on what the rest of the code assumes, you could allocate just the space for the string for each line instead of a full array, but you must change the node structure to use a char *t; instead of a line typedef. Note that it is very confusing to typedef arrays.
The only caveat is you must be careful when modifying these strings as you cannot add any characters at the end, nor insert any characters by moving contents beyond their allocated length. As a rule of thumb, if you reallocate these strings whenever you modify them, you should be safe.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
struct node *read_file(FILE *fp) {
char buf[128];
struct node *head = NULL, tail = NULL, *n = NULL;
while (fgets(buf, sizeof buf, fp)) {
buf[strcspn(buf, "\n")] = '\0'; // strip the trailing newline if present
n = malloc(sizeof(*n));
if (n == NULL)
abort();
n->prev = tail;
n->next = NULL;
n->t = strdup(buf);
if (n->t == NULL)
abort();
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
tail = n;
}
return head;
}

Traversing List in C

I'm trying to implement a linked list traversal, however my code is not working and I don't udnerstand why I've reassigned my pointer but it doesn't stick?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void inserter(Node *n1, int num){
if(n1==NULL){
Node *temp =(Node*)malloc(sizeof(Node));
temp->data=num;
temp->next=NULL;
n1=temp;
}
else{
Node *trav=n1;
while(trav!=NULL){
trav=trav->next;
}
}
}
int main(int argc, char **argv)
{
Node *l1 = NULL;
inserter(l1,l2,5);
inserter(l1,l2,11);
//It goes back into the NULL bracket despite me assigning it a node?
}
Here is the accompanying struct
typedef anode {
struct Node *next;
int data;
}Node;
Thank you for any help!I'm still new to all of this.
You're passing inserter() a pointer and an int. If you modify that int, no modifications would be visible from the calling function (I think you know that already). Same goes for the pointer: Node * is just a numeric type that holds an address, which has been passed by value.
If you want to modify where n1 points to, you'd need to dereference it. But because you don't want to change the contents of the memory that n1 points to, but change the value of n1 itself, your function would need to be passed a Node **.
Here's a quick example:
void inserter(Node **n, int num) {
if (*n == NULL) {
*n = malloc(...);
....;
}
....
}
That way you would change the actual value of n globally instead of just locally.

C: From char array to linked list

I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!

C program acting weird

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.

Passing an uninitialized struct to a function, why is it not null?

I've been scratching my head quite a while at this one. I'm creating my node without any values (and even tried initializing it and a pointer and set it = NULL), but when I get inside the insert function head_ does not evaluate to NULL. I can check for head_->id = NULL but I don't think I should have to do that. Any ideas on what I'm doing wrong? I'm trying to build and traverse a linked list and am certainly not off to a good start! The output is:
head_ =
not null!?
#include <stdio.h>
#include <stdlib.h>
struct node{
int id;
struct node *next;
};
int main(void){
struct node head;
int entered_id;
insert(&head, 1);
}
void insert(struct node* head_, int new_id){
printf("\nhead_ = %s", head_);
if(!head_){
printf("\nnull");
}
else
printf("\nnot null!?");
fflush(stdout);
}
#include <stdio.h>
#include <stdlib.h>
struct node{
int id;
struct node *next;
};
int main(void){
struct node * head = NULL; // create a pointer instead of declaring structure variable
int entered_id;
insert(head, 1);
}
void insert(struct node* head_, int new_id){
// printf("\nhead_ = %s", head_); can you print structure as string?
if(!head_){
printf("\nnull");
}
else
printf("\nnot null!?");
fflush(stdout);
}
If you use struct node head, it will create an object which occupies space and so is not NULL. What you want is a pointer to an object which initially points to nothing and so is null.
The struct is not a pointer to null because it was allocated. If it were declared as:
struct node *head;
then, it would possibly point to NULL, but its not defined.
struct node *head = NULL;
would guarantee its pointing to NULL. Even in that case, you can't allocate it in another function that way. If you in insert did
head = malloc(sizeof(struct node));
then, when main came back, head would still be NULL, and you would have a memory leak.
The way it is defined,
struct node head; //allocates sizeof(struct node) bytes on the stack of main, which is destroyed after main exits.
Make sense?

Resources