How to connect a struct in the other?

3

I started programming in C recently and I have a question about structs , I would like to know if it is possible to connect two structs to simulate a relationship between tables, for example struct categoria :

struct categoria
{
    int codigo_categoria;
    char descricao_categoria[20];
};

Related to struct produto :

struct produto
{
    char nome[30];
    int codigo_ligacao_categoria;
};

Is there a way to bind member codigo_categoria of struct categoria to member codigo_ligacao_categoria of struct produto ?

    
asked by anonymous 11.12.2015 / 15:56

1 answer

2

In C you can either have a struct of another type "embedded" in your original struct, as you can use "pointers" - a switch is a reference to another structure in memory - and in practice, compared to relational databases, it works like an "id" of another table - except instead of an ID number (which we often get addicted to see sequentially, cute numbers ID1, Id 2, id 3), we have memory address. (which in modern architectures is a 64bit number "#muitolouco").

I'll put the two examples:

struct categoria
{
    int codigo_categoria;
    char descricao_categoria[20];
};

struct produto
{
    char nome[30];
    struct categoria esta_categoria;
};

In this way, you have a complete category, independent of any other instance of the same data, within your product. It's simpler, because you do not have to worry about pointers logic, etc. - if you create a category, you can use a simple "=" sign to assign a copy of your category to the category within a product: / p>

struct produto meu_produto;
struct categoria minha_categoria;
...
meu_produto.esta_categoria = minha_categoria;
printf("Descrição da categoria: %s\n", meu_produto.esta_categoria.descricao);

This will copy all fields from the struct category to another struct within the product.

In real applications, this is usually not what you want - as you put it, the interesting thing is to have a reference to another category - which can be in an array, or another data structure - in this case, the syntax is:

struct categoria
{
    int codigo_categoria;
    char descricao_categoria[20];
};

struct produto
{
    char nome[30];
    struct categoria *esta_categoria;
};

...
meu_produto.esta_categoria = &minha_categoria;
printf("Descrição da categoria: %s\n", meu_produto.esta_categoria->descricao);

In this case, what stands in the struct product is a reference for the contents of the other struct (just like in the SQL relationship). If the original category struct is changed, the change can be seen by accessing the category through the product.

However, there is a fundamental difference to an SQL relationship - references to structures with pointers are valid only for the process that is running, loaded into memory. In a database reference, if you turn everything off, connect again, when loading the product, you will have a category_id that will still be valid in the category table.

In the C program, assuming you create or use a mechanism to persist the raw data of the structs between one execution and another of the program, by loading the data of a struct "product" the pointer it has for the category is invalid, and for all intents and purposes, points to a random region of memory. So for each struct that references others, on a system that needs to persist data - be it in bank, in file, in network, etc ... you have to create in a way associated with that struct functions to attach the related structs (and also to release the memory of related structs, when the main struct is deallocated) - for this example, you could have one:

struct categoria
{
    int codigo_categoria;
    char descricao_categoria[20];
    int referencias=0;
};

void produto_adiciona_categoria(struct produto *este_produto, struct categoria *esta_categoria) {
    *produto->esta_categoria = esta_categoria;
    esta_categoria->referencias += 1;
}

void produto_remove_categoria(struct produto *este_produto) {
    struct categoria *tmp = este_produto->categoria;
    este_produto->categoria=NULL;
    if (--(tmp->referencias) <= 0) {
        free(tmp)
    }
}
Note that even in a small application, to avoid memory leak problems, you would have to start counting how many references exist for each structure in memory - and create functions to create and destroy each type of structure based on the reference count - - management scales very fast - and when you realize it is creating an object-oriented system to do your program (and therefore reinventing the wheel).

I end with two suggestions: stop any attempt to develop your code to understand "pointers" in C - they are logical, and it is relatively easy to understand their mechanisms if we are focused on it - but if you let it in, and "well, in the example there's this *, so I'll put a * here and see if it works" - it gets complicated, tiring, and will generate aversive feelings.

The other recommendation: Unless you are doing this to learn C as your ultimate goal, not to have a functional program, I recommend using a higher-level language for this type of code. In dynamic languages like Python, Javascript, or Ruby, associating data as you want, which is done with "objects" in those languages, instead of C's structs is dozens of times simpler - especially for those who are just starting out.     

11.12.2015 / 17:53