I am new to C programming. Familiarising muself with struct pointers and linekd lists. I came across concept of linked list node with pointer to struct.
typedef struct
{
string name, surname;
int matriculation_num;
}Student_typedef;
typedef struct
{
Tstudent* student;
Node_typedef* next;
} Node_typedef;
Can anyone tell me what exactly is the purpose of Node_typedef. Where are such implementations usefull ?
Any useful link is much appreciated.
The two shown struct type definitions separate the stored data from the storing mechanism.
You can see that Student_typedef has only members which relate to information to store, but none relating to storing. The goal is to have a mechanism which can store a multitude of this data structure.
On the other hand Node_typedef does not contain any of the information to store, only a single pointer to the complete data. If the structure of the inforamtion to store would change (though still be reflected by the same type identifier Student_typedef), then nothing about this storage mechanism would have to be changed.
Or to describe it from a different angle, two developers working on a student database would only have to agree that all the needed information for each student is inside Student_typedef. Then one developer could handle programming functions to enter or edit a given struct (based on a pointer to the struct provided by the storage), while the other developer could handle storage aspects, like adding a new struct to fill, deleting, optimising memory, etc.
Such methods of interface definition and abstraction of code parts are necessary for efficiently handling large projects.
Related
I'm trying to implement a static linked list in C that holds any data type. I know that the node struct should use a void* but I also want each list to hold the same data type. That is, lists can hold any data type but every item in the list must be of the same type. I know using void* allows nodes to have any data type but how do I make it so that a list only contains items of the same type?
You can use the macro system to handle non void * lists... if you do something like:
#define LIST_OF(_type) struct node_of_##_type { \
struct node_of_##_type *prev, *next; \
_type data; \
}
then, you can declare as many list types as you want, you have only to say something like:
typedef char *string;
LIST_OF(string) *my_list = NULL;
/* will expend to something similar to:
struct node_of_string {
struct node_of_string *prev, next;
string data;
} *my_list = NULL;
*/
This is an attempt (well, too far yet to be comparable) to emulate the templates of C++. You will not have a list capable of storing anything, but a list adapted only to one type (but any type that can be typedef'd, as the type parameter must be a typename, not a type specification. And, as in C++, once you have that you have to instantiate every function using that type, to the proper type, forcing you to name it, (as functions cannot be overloaded in C) and to rewrite (by means of more macro expansions) to the actual code. Things get complicate soon, making it necessary some help from the language to use OOP techniques in C.
The problem with C is that it is a weakly typed language, this means that you can cast a Banana to a Truck and the compiler will be totally fine with that. Programmers in C are conditioned to keep this in mind and be very wary of what they are doing, that is to say it is the programmers responsibility to "think ahead" and make no such mistakes (e.g. like putting a Banana in a list of Trucks). You could work around this by adding another layer between your datatypes and the list nodes. A trust could hold a void* to the actual type together with an enum or an integer value representing the id of the data type you are trying to store in the list, you could call this a tagged node or something. The issue now becomes how to retrieve that tag or enum value. This will sadly add some boilerplate to your program, however, this might be automated using macro's.
Note that the problem you are highlighting (weak typing) is just part of the quirkiness of C. what I usually do in these situations is naming the variable holding the list accordingly and think very carefully of what I am doing with this variable.
A solution may be to, instead of using a List, use an array, this will at least produce a segmentation fault in some scenario's, but that will also be the case if you cast a Truck to a Banana and try to access fields which are out of memory range...
Hope this helps!
I was reviewing some libraries in C for a systems programming class, and I noticed their implementation of a doubly linked list did not require dynamically allocated data. Instead a list of a potentially dynamically allocated struct required an embedded list element, which with a list_entry macro would convert any list element back to the stored structure. For example given a struct foo:
struct list_elem
{
struct list_elem *prev;
struct list_elem *next;
};
struct list
{
struct list_elem head;
struct list_elem tail;
};
struct list foo_list;
list_init(&foo_list);
...
struct list_elem *e = list_begin(&foo_list);
struct foo *f = list_entry(e, struct foo, sharedelem); // Where sharedelem is of list_elem in struct foo
My question, is this advantageous and/or applicable outside of systems programming? Or would using an ambiguous type implementation of a linked list be preferable (wherein the linked list itself is malloc'ed and points to void elements).
There are two cases:
The program/library/service owns the data, and is not sharing it. In this case, altering the internal data structures to support different types of access/traversing (linked list, tree etc) can be advantageous, for speed and memory footprint reasons. However, this data should not leak to a client of the program/library/service, because the client code can mess with the internals (and eventually screwing it for all potential clients).
The program/library/service handles client's data on behalf of the client, so it shares it with the client code. In this case, the structures for accessing/traversing the client's data must "wrap" around it, without altering client's data. This is because the client code assumes data persistency from containers, e.g. "I gave you an int, I expect an int with the same value back".
I hope that these two cases explain why both approaches have merits, depending on the business case.
Im doing something like a supermarket simulator using C. I have a struct that keeps data from hundreds of fictional clients like so:
typedef struct clients {
int ID;
char Name[50];
}Clients;
I imported a .txt file containing these clients. It basically looks like this:
1234 Peter Parker
4724 Barack Obama
3851 John Wick
9428 Donald Trump
...
So now I have to simulate a supermarket, i have a timer that updates itself, picking random clients from the struct and put them inside the supermarket, i need to keep track how many of them and which of them are inside the supermarket. The thing is, i don't know how to like put the clients inside the market and store the data of those clients. For example, imagine client A and B enter the supermarket, how do I store those specific clients in the market, so that like i could search which of them are inside the market? Should I make a struct containing data from the struct Clients? I have no idea. Glad if you could help me.
You can create an array of your clients struct.
Here are some resources I found.
http://www.asic-world.com/scripting/structs_c.html
http://www.c4learn.com/c-programming/c-array-structure/
The answer is that there are many ways to do this, with pros and cons to each. If you care about performance and your data gets larger than hundreds and into the upper thousands then you probably start worrying about what type of data structure you're using, which then becomes a question about data structures and how you'll be searching for the names. If you're not so worried about performance, you can go for an array implementation where you create an array of Clients like so: which declares an array of 200 clients that you can assign values to.
Clients array[200];
The down side of this is if you get more Clients than you've allocated memory for, you'll have to either malloc more memory to fit it.
Alternatively you can go with the linked list implementation and create some sort of struct that represents a node with corresponding functions to manipulate it.
typedef struct {
Client *client;
node *next;
node *prev;
} node;
But this would require writing more code to add and remove nodes at minimum.
So, its really question of what YOU want.
EDIT:
If you just want to add a way of knowing if some client is in the super market why not create an enum and add it into the client struct? I prefer this over bool because then if you want to put someone in another place in the future, then you have the option to just add it to the enum.
enum place {
supermarket,
none
};
First thing that comes to mind is to use some kind of directed (or bidirected) list containing references to your Client structure. For instance,
typedef struct {
Client *client;
Visitor *next;
Visitor *prev;
} Visitor;
may be one of the nodes of that list. In the case of head or tail of the list, you can specify NULL values to distinguish different corner cases, but that depends on realization.
The list itself:
typedef struct {
Visitor *head;
Visitor *tail;
} VisitorList;
The drawback of such structure is that getting number of visitors has linear complexity which may be not that you want.
Say I'm writing an adventure game. The map is built of tiles of different types. I have tiles that form paths, and tiles that form doors, and so on.
I will use a struct to describe the type and content of a tile, and to which other tiles it connects.
Then I'll make a quadruple-linked list to connect them all together.
But a struct that will describe a room will have far more elements than one that will describe a door, so many elements in a door struct will be redundant. I could make a smaller door struct, but structs can only point to structs of the same type*, so I couldn't connect a room struct to a door struct. The redundancy may be negligible but I wondered if there's another way.
Another option is using an array of structs, but then I'd have lots of 'padding' structs wasting even more space. However an array would make reading and re-building a map from file much easier.
Is there any way around the limitation that a struct can only point to a struct of the same type? Or is there another common solution to this problem that I haven't mentioned?
One idea I had was that each tile could have pointers for every other type of tile. Some would be redundant, but it would be a lesser redundancy that the option above.
*By this I mean that typically in a linked list, structs contain pointers to struct of the same type that they're in.
You really don't have to have a uniform struct describing everything. Instead, you could do the following (this is somewhat like writing your own C++ virtual tables in C, and is very widely used).
Your basic tile struct can look like this:
struct tile
{
// common tile stuff
...
enum tile_type type;
void *type_info;
};
So in this struct you store stuff that's common to every tile type. Then you make other structs for other types: one for a room, one for a path, etc. Within an object of tile, you make the enum describe the actual type, and store a pointer to the concrete type within the void *.
There are many links describing variations of this technique. Here's one.
Instead of storing elements in a tile, store only a pointer to the linked list of elements.
I have a very basic question. In C, we declare a structure like so:
Snippet 1:
struct node {
int a;
int b;
char c;
};
I understand the basic concept behind structures. It can be viewed from many angles. It's a "structure", it is used to create a user defined type.
A structure is useless unless we define objects for it. We can create objects for it like so:
struct node obj1;
obj1.a=10; // corresponds to the value of obj1
obj1.c='A'; // ....
and so on..
Okay,
Now this following code snippet I cannot understand.
Snippet 2:
struct node {
node* left;
node* right;
int value;
};
How can we define node* left and node* right in the structure named node when the structure node hasn't even been completely formed yet?
What does it even mean? How can it point to something that hasn't even been formed yet?
How does it even know the size of the object to allocate when we create an object of node?
Can anyone help me out on this?
Edit: The code in the question is not valid C code, but it is valid C++ code
How can we define node* left and node* rightin the structure named node when the structure node hasn't even completely formed yet?
node * is pointer and a pointer does not require complete definition. Only declaration of type is enough.
What does it even mean? How can it point to something that hasn't even been formed yet?
Such structures are known as self-referencing. They can refer to the an object which (must)have same type as they have. This is one of the basis of linked list, trees, graph and many data structure.
How does it even know the size of the object to allocate when we create an object of node?
As object contains pointer, size of pointer is fixed and is known before knowing the complete object. Hence, size of object can be allocated. In this case, it will be size of data members+size of pointers+some padding.
Adding to the previous answer.
First you need to understand this What is the difference between a definition and a declaration?
Self referencing is a feature programming languages offer. It gives the user (the programmer) flexibility in building data types (graphs, linked list and many more).
Self referencing is using the fact that pointers could be declared and only be defined later. It sounds a little far fetched for the beginner, but the reason that is that pointers have a fix size of 4 bytes. Therefore, the compiler already knows how much memory to allocate for it and it assumes the pointer will be declared later on.
Hope I made it clearer