Allocating memory for nested linked list + using scanf - c

I'm struggling with allocating a memory for my linked list which is embedded in it's parent linked list - nested structure.
Structure declaration:
typedef struct parent
{
int x;
struct embed
{
int y;
int l;
struct embed *next;
}EMBED;
struct parent *next;
}PARENT;
Allocating memory for parent list:
PARENT *head = NULL;
PARENT *temp = (PARENT*)malloc(sizeof(PARENT));
What can't I figure out is how can I connect to that embedded list for allocating. Any ideas?
Also when we get to allocating memory and getting connection to that embedded list, I want to use a scanf function to store some data into that list but I do not know the connection declaration. How does it work, can someone explain?
Just so you know what am I working on, it is a school project for searching in a tree - starting from point A, finish at point B when inputs are numbers and in between them is a distance variable. So basically I want to find the shortest way (less calculations = short execution time) from getting to point B.
Thanks for suggestions.

Once the structure is properly defined, you can allocate an embedded list element like so:
temp->EMBED.next = malloc(sizeof(struct embed));

You don't need that inner typedef inside the struct definition. In fact, my GCC doesn't like it. This works:
typedef struct parent
{
int x;
struct embed
{
int y;
int l;
struct embed *next;
} embed;
struct parent *next;
} PARENT;
With this, you can allocate and fill a list with something like this:
PARENT p;
/* build up a list */
p.embed.next = NULL;
for (i = 0; i < 5; i++) {
struct embed *new = malloc(sizeof *new);
new->next = p.embed.next;
printf("enter a number:\n");
scanf("%d", &new->y);
p.embed.next = new;
}

Related

Implementing a simple linked list in C without malloc

All the implementations I have seen online use pointer to declare nodes and then will use malloc to create space for them like this:
struct Node
{
int data;
struct Node *next;
};
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
...
But I can also create the same without pointers and malloc like this:
struct node {
int id;
struct node* next;
};
struct node head = {0, NULL};
struct node one = {1, NULL};
struct node two = {2, NULL};
struct node tail = {3, NULL};
int main(){
head.next = &one;
one.next = &two;
two.next = &tail;
...
My question is, why the 1st method is mostly the one used, why do we need to declare each node as pointer and why do we need malloc?
(Just to point out I know why struct Node *next; is declared as pointer int the struct declaration).
You should do this with local variables, not global ones, but the general idea would be the same. You should also steer towards having arrays and not heaps of otherwise unrelated variables:
struct node {
int id;
struct node* next;
};
int main(){
struct node nodes[4];
for (int i = 0; i < 4; ++i) {
nodes[i].id = (3 - i);
if (i != 0) {
nodes[i].next = &nodes[i-1];
}
}
return 0;
}
Where something like that assembles them in reverse order for convenience, but they're all grouped together in terms of memory initially.
malloc is used because you often don't know how many you're going to have, or they get added and removed unpredictably. A general-purpose solution would allocate them as necessary. A specialized implementation might allocate them as a single block, but that's highly situational.
Here the lifespan of nodes is within that function alone, so as soon as that function ends the data goes away. In other words:
struct node* allocateNodes() {
struct node nodes[10];
return &nodes; // Returns a pointer to an out-of-scope variable, undefined behaviour
}
That won't work. You need a longer lived allocation which is precisely what malloc provides:
struct node* allocateNodes() {
struct node *nodes = calloc(10, sizeof(struct node));
return nodes; // Returns a pointer to an allocated structure, which is fine
}
The problem is if you malloc you are responsible for calling free to release the memory, so it becomes more work.
You'll see both styles used in code depending on the required lifespan of the variables in question.
If you know ahead of time exactly how many items will be in your list, then you're probably better off using an array rather than a list. The whole point of a linked list is to be able to grow to an unknown size at runtime, and that requires dynamic memory allocation (i.e., malloc).

Define a struct with a member pointing to another member

I'm trying to program a network in C. I have nodes which are linked to each other and I 'd like to do that by making the struct member point to another member (not to another node, because I want to preserve the identity of the links).
The code I made to do that is something like:
struct node{
int k; //number of links
struct node.link **link; //<- wrong
};
but this is not right as node is not a variable but a type of variable (this is already discussed as an error in another QA: first you have to define a variable of node type and then apply the .link, but this doesn't help here). There's also a QA called "Struct member point at another struct member" but they don't do it from definition and it is not so clear how to generalize it (at least for me).
Is it a correct way to do this?
The problem is that the C language doesn't let you create the type you want. You need a type T with the property *T has the same type as T. You can't do that. (Well, function pointers have that property, but that's an irrelevant technicality.)
You have to introduce a new name. C only lets you do this with structs or similar constructions.
struct link {
struct link *ptr;
};
struct node {
int k;
struct link *link;
};
This will get you what you want. Now, in order to go from a struct link * to a struct node *, you'll have to do some pointer math:
struct node *node_from_link(struct link *link) {
return (struct node *) ((char *) link - offsetof(struct node, link));
}
This is also provided by the container_of macro, which is not part of the C standard, but you can find a definition for it online.
Or, you could just go the traditional route.
// Usually easier to do it this way...
struct node {
int k;
struct node *link;
};
Is this what you are after?
struct Node
{
int k; //number of links
void* link;
};
struct Node* create()
{
struct Node* node = malloc(sizeof(struct Node));
node->k = 0;
node->link = 0;
return node;
}
void link(struct Node* from, struct Node* to)
{
from->link = &(to->link);
}
int main()
{
struct Node* child = create();
struct Node* parent = create();
link(parent, child);
return 0;
}
I've used void* for the link for the reason expressed by Dietrich: you want a pointer to the link to be the same type as the link. This effectively means a cast, so why not just use a generic pointer?
Membership in a structure, generalized or specific, is not an attribute of C data types. There is therefore no way to declare a pointer that can only point to a structure member, and not to any other variable of compatible type.
On the other hand, you don't need to do anything special to declare a pointer that can point to a member of another structure. You just need a pointer to that member's data type, and structure membership is irrelevant to that data type.
For example, you can have
struct node {
int k; /* number of links */
struct node **links; /* points to a dynamic array of node pointers */
struct node **one_link; /* points to a node pointer from another node */
};
In that case, it might make sense to do something like this:
struct node *n1 = /* ... */;
struct node *n2 = /* ... */;
n2->one_link = &(n1->links[3]);
Overall, though, I think this is kind of convoluted. There is probably a better way to structure your data.
Update:
Based on your description of what you're after:
[...] links are bidirectional, if I destroy one link (say the one that links node 1 to node 3) I'll need to destroy the node 1 link AND the corresponding link from node 3. Then I need to know more than just who is link to who. I need to know which link they are using.
there are at least two possible solutions, depending on details of how your nodes are structured. If they are structured like I show above, with an array (dynamic or not) of pointers to other nodes, then your general idea simply won't work. That's because the position of each link within an array of links will change as you delete other links (supposing that you close the gaps). Instead, you can just scan:
struct node {
int k; /* number of links */
struct node **links; /* points to a dynamic array of node pointers */
struct node *parent; /* points to a node that links to this one */
};
void delete_node(struct node *n) {
if (n->parent) {
int i;
for (i = 0; i < n->parent->k; i += 1) {
if (n->parent->links[i] == n) {
/* ... delete the ith element of n->parent->links ... */
break;
}
}
}
/* ... clean up node n ... */
}
If one node's links to others are stored in separate members, on the other hand, then you could indeed provide a double-pointer by which to remove links from the parent, but the presence of member k in your original structure tells me that's not your situation.
Ok, this is how I finally solved it in my program:
typedef struct node{
int k; //connectivity
struct link **enlace; //vector of LINKs
}NODE;
typedef struct link{
NODE *node1;
NODE *node2;
}LINK;
Basicly, I defined two structures: one is the NODE type, which contains the information of how connected is the node and a vector of LINKs, and the other is the structure LINK which contains the information of the link itself, I mean which nodes the link connects.
With these two I'm able to create the network of nodes with a connectivity following a Poisson distribution, and then destroy each link one by one, choosing one link at random from a list and then redirecting the pointers of each node to NULL.

A Hashset that holds a generic linked list that holds a generic linked list

This is my data structure for an Assignment I'm doing in class. I'm supposed to implement a a hash set that holds a string of linked lists. Each of those individual linked lists holds an int. My list is generic, if it works, using (void* data) like this:
typedef struct NodeStruct {
void *data;
struct NodeStruct* next;
struct NodeStruct* prev;
} NodeStruct;
// Rename NodeStruct* as NodePtr
typedef NodeStruct* NodePtr;
typedef struct ListStruct {
int elementType;
NodePtr first;
NodePtr last;
NodePtr current;
} ListStruct;
// ListHndl is just a ListStruct* renamed.
First question: Right now, I"m using memcpy(list->data, data, list->elementType).
I was wondering.. is it okay do just store it directly, like list->data = data?
This is my hash set struct:
typedef struct HashStruct {
int size;
int load;
ListHndl *chain; //An array of Linked Lists.
} HashStruct;
typedef HashStruct* HashHandle
HashHandle new_hashset(int size) {
HashHandle tempHash = malloc (sizeof (HashStruct));
assert (tempHash != NULL);
tempHash->size = size;
tempHash->load = 0;
tempHash->chain = malloc (sizeof (ListHndl) * size);
assert(tempHash->chain != NULL);
for (int i = 0; i < size; i++) {
tempHash->chain[i] = newList(sizeof(char*));
tempHash->chain[i]->data = malloc(sizeof (ListHndl)); // Error here
}
return tempHash;
}
This is the error that I'm getting.
hash.c: In function ‘new_hashset’:
hash.c:28:27: error: dereferencing pointer to incomplete type
tempHash->chain[i]->data = malloc(sizeof (ListHndl));
^
Second question: I'm not sure how I'm supposed to be allocating memory for these linked lists, which is probably why I got this error.
Am I even implementing this data structure correctly? If more information is needed, please let me know. Thank you!
First question: Right now, I"m using memcpy(list->data, data, list->elementType). I was wondering.. is it okay do just store it directly, like list->data = data?
That depends on what 'data' is pointing to. It is quite common to list->data = data when 'data' is pointing to memory allocated from the heap,
Second question: I'm not sure how I'm supposed to be allocating memory for these linked lists, which is probably why I got this error.
For the typedefs outlined in the question, you will need to allocate memory for:
Each new node: newNode=malloc(sizeof(NodeStruct))
Each node payload: newNode->data = malloc(sizeof(int))
Am I even implementing this data structure correctly?
It is difficult to say with the limited code provided. Of course, there are many ways to accomplish the assigned task; including those ways that are easier to understand, as well as those which are specifically tuned for performance.

malloc array of structs in a struct

I have a struct called course and each course has multiple nodes (another struct 'node').
The number of nodes it has varies but I am given that number from a file that I am reading this information from, so that number sits in a variable.
So I need a malloc inside the struct. But I am confused. I know you can have arrays in structs but I don't know where to put the code that creates the malloc array since my struct is in my header file. Here's my code at the moment. I realize it looks wrong, I just don't know how I can fix it and where to initialize the malloc array.
struct course {
char identifier[2];
int num_nodes;
struct node *nodes;
nodes = (struct nodes*)malloc(num_nodes*sizeof(struct node));
};
struct node {
int number;
char type[2];
};
I want to be able to do something like:
struct node a_node;
struct course a_course;
a_course.nodes[0] = a_node;
etc...
I haven't used much C, this is the first time I've ever tried using dynamic arrays in C. My experience all comes from Java, and of course Java doesn't really use pointers in the same way as C so it's all a tad confusing for me.
So some help would be much appreciated, thanks a lot :)
The easiest approach is to create a function which initialises the struct:
void init_course(struct course* c, const char* id, int num_nodes)
{
strncpy(c->identifier, id, sizeof(c->identifier));
c->num_nodes = num_nodes;
c->nodes = calloc(num_nodes, sizeof(struct node));
}
For symmetry, you could also then define a destructor
void destroy_course(struct course* c)
{
free(c->nodes);
}
These would have usage like
struct course c;
init_course(&c, "AA", 5);
/* do stuff with c */
destroy_course(&c);
The purpose of malloc (or calloc - which I prefer to use for structs) is to dynamically allocate the memory at runtime. So, your struct should look like this, since it is an object definition:
struct course {
char identifier[2];
int num_nodes;
struct node *nodes;
};
Somewhere else in your program that uses the course struct, you will need to allocate memory (i) for any course objects you create and (ii) any node objects in that course.
e.g.
main()
{
// lets say 1 course
struct course *my_course;
my_course = calloc(1, sizeof(struct course));
// lets say 3 nodes in that course
struct node *my_nodes;
my_nodes = calloc(3, sizeof(struct node));
my_course.num_nodes = 3;
my_course.nodes = my_nodes;
//...
// clean up
free(my_nodes);
free(my_course);
}
Now, you are good. Make sure to free the memory before exiting.
it is also possible to direct allocate the structs in structs this way:
first declare your struct:
struct course {
char identifier[2];
int num_nodes;
struct node *nodes;
};
then in your program
main(){
int i;
struct course *c;
c = malloc(sizeof(struct course));
c->num_nodes = 3;
c->nodes = malloc(sizeof(struct node)*c->num_nodes);
for(i=0; i<c->num_nodes; i++)
c->nodes[i] = malloc(sizeof(struct node));
//and free them this way
for(i=0; i<c->num_nodes; i++)
free(c->nodes[i]);
free(c->nodes);
free(c);
}
or do it the way above what ever you like

Structures inside linked lists in C

I'm learning how to implement linked lists in C. I understand the basics of normal linked lists, how to add values, how to print them etc. but I've been wondering - is it possible to add other structure as a value in linked list? What I mean is:
typedef struct personal_info {
char *name;
char *surname;
int phone_number;
} Info;
typedef struct llist {
Info *info;
struct llist *next;
} List;
And when I do this, how do I access the values of the Info structure?
List *l;
l = malloc(sizeof(List));
l->info->name = 'name';
l->info->surname = 'surname';
l->info->phone_number = 1234567890;
The code crashes, so I'm definitely doing something wrong. Could you give me some tips how to achieve that?
You also need to allocate memory for the info struct:
l = malloc(sizeof(List));
l->info = malloc(sizeof(Info));
l->info->name = "name";
l->info->surname = "surname";
l->info->phone_number = 1234567890;
List *l;
l = malloc(sizeof(List));
l->info = malloc(sizeof(Info));
You have to malloc memory for the struct as well
Also remember that if you're implementing any functions that remove nodes from the list, you need to free that struct before you free the node.

Resources