IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Tableau de structure alloué dynamiquement


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2009
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 20
    Points : 12
    Points
    12
    Par défaut Tableau de structure alloué dynamiquement
    Bonjour à tous,
    Cela fait un moment que je n'ai pas touché au C, le trouvant un peu trop bas niveau à mon goût, je m'y suis tous de même remis.
    J'ai donc réalisé un petit programme ayant pour rôle d'associer à un mot un "token" sur lequel je ferais des traitement plus tard. Malheureusement, la mémoire se rebelle et ne veut pas se laisser manipuler :-°

    Je m'explique : j'ai crée une structure de données SymbolTable définie dans symbolTable.h.
    Son rôle est d'attribuer un mot à un token.
    J'ai crée 2 fonctions, l'une pour allouer la mémoire pour la structure allocate_Symbol_Table_Memory( SymbolTable** symbolTable ) et une pour ajouter un couple add_Symbol( SymbolTable** symbolTable, const int size, char* symbol, char* token ).
    Jusque là tout fonctionne l'allocation se passe parfaitement, malheureusement je ne peux pas accéder aux zones de mémoires alloués dans mes fonctions, ça plante à l'exécution. En revanche, si je tente d'y accéder à partir de mon main aucun problème.

    Comme un code parle mieux que des explications, voici mon code :
    main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
    #include <stdlib.h>
    #include "symbolTable.h"
     
    int main( void ) {
    	SymbolTable *symbolTable = NULL;
     
    	int size = allocate_Symbol_Table_Memory( &symbolTable );
    	//si je tente de modifier dans le main, ça fonctionne
    	symbolTable[0].symbol = "";
    	//add_Symbol( &symbolTable, size, "if", "<cond>" );
     
    	return EXIT_SUCCESS;
    }
    symbolTable.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #ifndef __SYMBOL__TABLE__
    #define __SYMBOL__TABLE__
     
    //taille de la table des symboles
    #ifndef SYMBOL_TABLE_SIZE
    	#define SYMBOL_TABLE_SIZE 5
    #endif
     
    //un symbole est associé à un token, utilisé plus tard pour la construction de l'arbre abstrait de données
    typedef struct SymbolTable SymbolTable;
    struct SymbolTable
    {
    	char* symbol;
    	char* token;
    };
     
    //alloue un emplacement mémoire nécessaires pour que la table des symboles puisse fonctionner correctement
    int allocate_Symbol_Table_Memory( SymbolTable** symbolTable );
    //ajoute un couple (symbole, token) dans la table des symboles
    int add_Symbol( SymbolTable** symbolTable, const int size, char* symbol, char* token );
     
    #endif
    symbolTable.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include <stdlib.h>
    #include <stdio.h>
    #include "symbolTable.h"
     
    //alloue la mémoire nécessaire pour la Table des Symboles
    //utilise la constante SYMBOL_TABLE_SIZE définie dans symbolTable.h
    int allocate_Symbol_Table_Memory( SymbolTable** symbolTable )
    {
    	int i = 0;
    	*symbolTable = (SymbolTable*)calloc(SYMBOL_TABLE_SIZE, sizeof(SymbolTable));
    	if( *symbolTable == NULL )
    	{
    		fprintf(stderr, "Impossible d'allouer la table des symboles.");
    	}
    	//pour le test
    	printf( "%s", symbolTable[0]->symbol );
    	//ça plante ici, dès que je veux accéder au contenu de symbolTable[i]->symbol ou symbolTable[i]->token
    	while( i != SYMBOL_TABLE_SIZE )
    	{
    		symbolTable[i]->symbol = "";
    		symbolTable[i]->token = "";
    		i++;
    	}
    	return SYMBOL_TABLE_SIZE;
    }
     
    //ajoute un couple (symbole, token) dans la table des symboles
    //retourne -1 si la table des symboles est pleine
    //retourne l'indice auxquels le couple a été ajouté si tout s'est bien passé
    int add_Symbol( SymbolTable** symbolTable, const int size, char* symbol, char* token )
    {
    	int i = 0;
    	//on parcourt la table tant qu'on est pas arrivé au dernier élément et qu'il y a un symbole à l'indice
    	while( (i != size) && (symbolTable[i++]->symbol == "") );
    	if( i == size )
    	{
    		fprintf(stderr, "Impossible d'ajouter un symbole dans la table des symboles.");
    		return -1;
    	}
    	symbolTable[i]->symbol = symbol;
    	symbolTable[i]->token = token;
    	return i;
    }
    Voilà si quelqu'un a une petite idée je lui serais très reconnaissant, ça doit sans doute être une erreur bête mais je ne la vois pas.
    Et au passage tout commentaire sur le code, sur des améliorations et optimisations sont les bienvenues.

    Merci d'avance

  2. #2
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 800
    Points
    1 800
    Par défaut
    je vais tester ton code et je te dis. sinon pour l'instant a premiere vue je vois 2 probleme dont le premier n'a aucune influence pour l'instant.
    1/ dans ta fonction d'allocation quand tu testes si le pointeur est null tu te contente seulement d'afficher un message puis tu continues. dans ce cas si il y erreur ton programme plantera plus tar de toute facon car tu ne l'as pas stopper. dont ajoute quelquechose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if( *symbolTable == NULL )
    	{
    		fprintf(stderr, "Impossible d'allouer la table des symboles.");
                    return -1;  //pour sortir de la fonction et dans ton main si size==-1 return 0;
    	}
    2/ton probleme se situe au niveau de l'allocation. pour te guider testes ces deux codes:

    1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    printf( "%s\n", symbolTable[0]->symbol);
    	//ça plante ici, dès que je veux accéder au contenu de symbolTable[i]->symbol ou symbolTable[i]->token
                puts("ca marche bien hein !");
    2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    printf( "%s\n", symbolTable[1]->symbol);
    	//ça plante ici, dès que je veux accéder au contenu de symbolTable[i]->symbol ou symbolTable[i]->token
                puts("ca marche bien hein ! ooh ce message n'apparaitra pas!");
    Petit lien vers mon premier jeux SDL2/C
    http://store.steampowered.com/app/72..._Soul_Of_Mask/
    la suite? ca vient,ca vient!

  3. #3
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 800
    Points
    1 800
    Par défaut
    bon pour etre honnete quand je fais une allocation dans une fonction j'utilise plus la forme

    pointer = fonction_allocation(taille ); type *func(size);

    plustot que

    fonction_allocation(&pointer,taille); void func(type **p,size);

    car j'ai jamais vraiment compris la chose donc en modifiant le minimum voici ton code qui marche. je l'ai teste chez moi et c'est bon. pas d'erreur. mais code_qui_marche != code_propre

    main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int main( void ) {
    	SymbolTable *symbolTable = NULL;
     
    	int size = allocate_Symbol_Table_Memory( &symbolTable );
    	int i;
    	//si je tente de modifier dans le main, ça fonctionne
     
    	add_Symbol( symbolTable, size, "if", "<cond>" );
        add_Symbol( symbolTable, size, "for", "<test>" );
        add_Symbol( symbolTable, size, "and", "<elemt>" );
        add_Symbol( symbolTable, size, "j'aime", "<le C>" );
        add_Symbol( symbolTable, size, "j'aime pas", "<la politique>" );
     
        for(i=0;i<5;i++)
            printf("sym=\" %s %s\"\n",symbolTable[i].symbol,symbolTable[i].token);
     
     
    	return EXIT_SUCCESS;
    }
    symbolTable.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    int allocate_Symbol_Table_Memory( SymbolTable** symbolTable )
    {
    	int i = 0;
    	SymbolTable *p = *symbolTable;
    	p = (SymbolTable*)calloc(SYMBOL_TABLE_SIZE, sizeof(SymbolTable));
    	if( p == NULL )
    	{
    		fprintf(stderr, "Impossible d'allouer la table des symboles.");
    		return -1;
    	}
    	//pour le test
     
    	//printf( "%s\n", p[0].symbol);
    	//ça plante ici, dès que je veux accéder au contenu de symbolTable[i]->symbol ou symbolTable[i]->token
    	while( i < SYMBOL_TABLE_SIZE )
    	{
    		p[i].symbol = "";
    		p[i].token = "";
    		i++;
    	}
     
        *symbolTable = p;
     
    	return SYMBOL_TABLE_SIZE;
    }
     
    //ajoute un couple (symbole, token) dans la table des symboles
    //retourne -1 si la table des symboles est pleine
    //retourne l'indice auxquels le couple a été ajouté si tout s'est bien passé
    int add_Symbol( SymbolTable* symbolTable, const int size, char* symbol, char* token )
    {
    	int i = 0;
    	//on parcourt la table tant qu'on est pas arrivé au dernier élément et qu'il y a un symbole à l'indice
    	while( (i != size) && (strcmp(symbolTable[i].symbol,"")) )
    	{
    	    i++;
    	}
     
    	if( i == size )
    	{
    		fprintf(stderr, "Impossible d'ajouter un symbole dans la table des symboles.");
    		return -1;
    	}
    	symbolTable[i].symbol = symbol;
    	symbolTable[i].token = token;
    	return i;
    }
    notes les modifications.
    dans alloc j'ai mit p=*symbole et quand tout est ok *symbole = p

    dans add. ton while posait deja 2 probleme. en c on compare des chaines avec strcmp ou manuellement mais pas str=="". deuxieme probleme le p[i++] faisait que quelque soit le cas le premier serait toujours saute.car meme si le test est ok i est pas =0 mais a 1 donc tu assigneras pas a la valeur de i souhaite mais a i+1.

    voila. moi personnellement j'aurai fait pour l'allocation:
    symbole = allocation();
    car je l'ai dit je maitrise pas la forme
    allocation(&symbole);

    si quelqu'un autre peut intervenir pour resoudre son probleme de maniere plus propre que moi je serai tres interresse.
    Petit lien vers mon premier jeux SDL2/C
    http://store.steampowered.com/app/72..._Soul_Of_Mask/
    la suite? ca vient,ca vient!

  4. #4
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonjour,
    Personnellement, j'aurais tendance à adopter une approche légèrement différente.
    Pour la suite, les noms que j'emploie ne sont que des suggestions, tu peux garder ceux que tu as mis.


    Tout d'abord, ta manière de faire t'oblige à stocker séparément ta table et sa taille.
    Ce n'est pas très pratique, si ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    struct SymbolTableElmt {
        char* symbol;
        char* token;
    };
     
    /* Éventuellement */
    typedef struct SymbolTableElmt SymbolTableElmt;
     
     
    struct SymbolTable {
        SymbolTableElmt* elements;
        size_t size;       /* Taille réellement occupée */
        size_t max_size;   /* Taille allouée */
        /* Tu peux mettre des "int" si tu préfères */
    };
     
    typedef struct SymbolTable SymbolTable;
    De cette manière, on sépare les éléments eux-mêmes de la structure (au sens large) qui les contient.
    Je ne sais pas si tu as déjà programmé des listes chaînées en C, en général on fait une structure pour les « maillons » et une structure pour la « liste » proprement dite.
    Ici c'est pareil.

    Si je conserve à la fois la taille allouée et la taille occupée par la table, c'est pour éviter de recalculer la dernière à chaque fois.
    Mais ce n'est pas indispensable.

    Tu peux même définir la structure des éléments (ou les deux) dans le fichier d'implémentation, si tu veux cacher la manière d'implémenter la table de symboles.


    La fonction d'allocation…
    Citation Envoyé par lilington Voir le message
    pour etre honnete quand je fais une allocation dans une fonction j'utilise plus la forme

    pointer = fonction_allocation(taille ); type *func(size);

    plustot que

    fonction_allocation(&pointer,taille); void func(type **p,size);
    Je suis d'accord.
    Pas parce que je ne maîtrise pas la seconde forme, mais parce que la première me paraît plus cohérente.
    L'adresse de la mémoire est le résultat de l'allocation, et la taille est un paramètre nécessaire à cette allocation, pas l'inverse.
    Enfin il me semble.

    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    #include <stdlib.h>
     
     
    SymbolTable* SymbolTable_allocate(size_t max_size)
    {
        SymbolTable* st = malloc(sizeof(SymbolTable));
        if (st == NULL) {
            fputs("Pas assez de mémoire.\n", stderr);
            return NULL;
        }
     
        st->size = 0;
        st->max_size = max->size;
        st->elements = calloc(max_size, sizeof(SymbolTableElmt));
        if ((max_size > 0) && (st->elements == NULL)) {
            fputs("Pas assez de mémoire.\n", stderr);
            free(st);   /* Ne pas oublier ce qui a déjà été alloué ! */
            return NULL;
        }
        else
            return st;
    }
    Et voilà !
    Mais cette façon de faire oblige à allouer dynamiquement la table des symboles, ce qui n'est pas forcément voulu.
    Alors on peut combiner avec une fonction d'initialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <stdio.h>
    #include <stdlib.h>
     
     
    SymbolTable* SymbolTable_allocate(size_t max_size)
    {
        SymbolTable* st = malloc(sizeof(SymbolTable));
        if (st == NULL) {
            fputs("Pas assez de mémoire.\n", stderr);
            return NULL;
        }
     
        if (SymbolTable_intialize(st, max_size) != 0) {
            free(st);
            st = NULL;
        }
     
        return st;
    }
     
     
    /* Retourne 0 en cas de succès, une valeur non nulle en cas d'erreur */
    int SymbolTable_intialize(SymbolTable* st, size_t max_size)
    {
        SymbolTableElmt* elmts;
     
        if (st == NULL)
            return -1;
     
        elmts = calloc(max_size, sizeof(SymbolTableElmt));
        if ((max_size > 0) && (elmts == NULL)) {
            fputs("Pas assez de mémoire.\n", stderr);
            return 1;
        }
     
        /* Ainsi, st n'est modifiée que si l'allocation a réussi */
        st->size = 0;
        st->max_size = max->size;
        st->elements = elmts;
        return 0;
    }
    Le type de retour de la fonction d'initialisation est assez libre.
    Cela peut être un entier comme ici, mais on peut aussi retourner un booléen (stdbool.h), ou encore un pointeur sur SymbolTable : un pointeur sur la talbe initialisée en cas de succès, NULL, en cas d'erreur.


    Tu remarqueras que, contrairement à toi, je n'initialise pas les éléments.
    Puisque la fonction « calloc » le fait, pourquoi m'embêter ?
    Après l'appel, tous les champs « symbol» et « token » valent 0, soit « NULL ».
    Mais bien entendu, rien ne t'empêche de tout de même leur affecter une valeur.
    En passant, NULL me paraît être une valeur plus appropriée que la chaîne vide pour indiquer qu'un élément est vide, et de plus est beaucoup plus facile à tester.

    Pendant qu'on y est, quelques remarques sur ce que tu as écrit.
    lilington t'a indiqué pourquoi ton programme plantait, et a résolu le problème en ajoutant une variable temporaire (« p ») du bon type.
    Mais si tu souhaites t'en passer, c'est possible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while (i < SYMBOL_TABLE_SIZE)
    {
        (*symbolTable)[i].symbol = "";
        (*symbolTable)[i].token = "";
        i++;
    }
    Ta variable « symbolTable » étant un pointeur sur la tableau, il faut d'abord déréférencer ce pointeur avant de pouvoir accéder aux éléments du tableau.

    Il se trouve que ce bout de code est typiquement un cas d'utilisation de la boucle « for ».
    En plus il te permet d'éviter un des problèmes que tu as rencontré :
    Citation Envoyé par lilington Voir le message
    deuxieme probleme le p[i++] faisait que quelque soit le cas le premier serait toujours saute.car meme si le test est ok i est pas =0 mais a 1 donc tu assigneras pas a la valeur de i souhaite mais a i+1.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for (i = 0; i < SYMBOL_TABLE_SIZE; ++i)
    {
        (*symbolTable)[i].symbol = "";
        (*symbolTable)[i].token = "";
    }
    Après, si tu n'aimes pas la boucle « for »…


    Sinon, lorsque tu veux ajouter un symbole, tu ne vérifies pas s'il est déjà présent ou pas !!
    C'est important tout de même, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <stdio.h>
    #include <string.h>
     
     
    /* Retourne 0 si l'ajout a été effectué, une valeur non nulle sinon
     * Encore une fois, on peut retourner un booléen à la place
     * Ou on peut retourner la nouvelle taille de la table */
    int SymbolTable_add_symbol(SymbolTable* st, char* symbol, char* token)
    {
        int i;
     
        if ((st == NULL) || (symbol == NULL) || (token == NULL))
            return -1;
     
        if (st->size == st->max_size) {
            puts("Plus de place dans la table");
            return 1;
        }
     
        /* Si l'on ne garde pas en mémoire la taille occupée, la condition d'arrêt devient quelque chose comme :
         * (i < st->max_size) && (st->elements[i].symbol != NULL) */
        for (i = 0; i < st->size; ++i) {
            /* Si le symbole est déjà présent... */
            if (strcmp(symbol, st->elements[i].symbol) == 0) {
                /* ... soit on ne fait rien... */
                printf("Symbole « %s » déjà présent\n", symbol);
                return 2;
     
                /* ... soit on remplace le token existant */
                st->elements[i].token = token;
                return 0;
            }
        }
     
        /* Si on arrive ici, c'est qu'il faut ajouter le symbole */
        /* Attention, si on ne conserve par la taille occupée, il faut tout de même vérifier que la taille maximale n'est pas atteinte */
        st->elements[st->size].symbol = symbol;
        st->elements[st->size].token = token;
        ++st->size;
        return 0;
    }
    J'aimerais mettre le doigt sur un point important de l'affectation de chaînes de caractères en C.
    Lorsque l'on utilise l'opérateur d'affectation (« = »), on se contente de recopier l'adresse de la chaîne de caractères.
    Si, par la suite, cette adresse devient invalide ou la chaîne est modifiée, ce sera répercuté sur la variable précédemment affectée.
    Donc on ne fait une affectation directe que lorsque l'on est sûr que la chaîne que l'on affecte restera valide tout le long de la durée de vie de la variable affectée.

    Dans le cas contraire, il faut impérativement copier le contenu de la chaîne, et pas seulement son adresse.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /* On est absolument certain que la chaîne pointée par s ne sera jamais invalidée ni modifiée pendant toute la durée de vie de s2 */
    void f(char* s)
    {
        char* s2;
        (...)
        s2 = s;
        (...)
    }
     
     
    /* La chaîne pointée par s est susceptible d'être modifiée durant la durée de vie s2 */
    #include <string.h>
     
    void g(char* s)
    {
        char* s2;
        (...)
        strcpy(s2, s); /* Attention : s2 doit pointer sur une zone allouée qui contient suffisamment de place */
        (...)
    }

    Une petite remarque en passant.
    La notation « st->elements[i].symbol » peut sembler lourde pour certains.
    On peut très bien l'éviter en utilisant une variable intermédiaire, qui servira d'« itérateur » :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SymbolTableElmts *p;
    (...)
    for (p = st->elements; (p - st->elements) < st->size; ++p) {
        if (strcpy(symbol, p->symbol) == 0) {
            (...)
        }
    }
    Si tu veux plus d'explications sur ce code, n'hésite pas !


    Il faut bien sûr penser à la libération des ressources.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdlib.h>
     
    void SymbolTable_deallocate(SymbolTable* st)
    {
        if (st != NULL) {
            if (st->elements != NULL)
                free(st->elements);
            free(st);
        }
    }
    Si on a défini la fonction d'initialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdlib.h>
     
    void SymbolTable_deallocate(SymbolTable* st)
    {
        if (st != NULL) {
            SymbolTable_free(st);
            free(st);
        }
    }
     
    /* Bon, je ne suis pas très inspiré pour le nom de la fonction… */
    void SymbolTable_free(SymbolTable* st)
    {
        if (st != NULL) {
            if (st->elements != NULL) {
                free(st->elements);
                st->elements = NULL;
                st->size = 0;
            }
        }
    }
    On peut aussi penser à une fonction « reset », qui supprime les éléments stockés, puis réalloue la tableau avec une taille différente.
    Finalement, il s'agit d'un appel à « free » suivi d'un appel à « initialize ».

    Pour le reste, tout dépend des fonctionnalités que tu veux donner à ta table de symboles.


    Bon, je t'ai mis des petits bouts un peu partout.
    J'espère que tu arriveras à les mettre les uns avec les autres.
    Si tu as des soucis, n'hésite pas à demander.
    Mais essaye de faire quelque chose avant !

  5. #5
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 800
    Points
    1 800
    Par défaut
    je crois que tout est claire
    et merci pour les reponses a mes interrogations en bonus
    Petit lien vers mon premier jeux SDL2/C
    http://store.steampowered.com/app/72..._Soul_Of_Mask/
    la suite? ca vient,ca vient!

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lilington Voir le message
    bon pour etre honnete quand je fais une allocation dans une fonction j'utilise plus la forme

    pointer = fonction_allocation(taille ); type *func(size);

    plustot que

    fonction_allocation(&pointer,taille); void func(type **p,size);

    car j'ai jamais vraiment compris la chose
    C'est pas la manière de programmer la plus brillante qui soit que d'avancer en disant "je fais ceci car ça marche même si je pige rien à ce que je fais". Surtout en C où un truc foireux peut marcher 15 jours et planter le 16° parce qu'on a rajouté un simple "printf()" ...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre à l'essai
    Inscrit en
    Juillet 2009
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Merci de cette réponse très complète et de toutes ces remarques pertinentes sur mon code.
    J'ai adapté mon code à présent cela fonctionne nikel. J'avais oublié à quel point gérer soi-même la mémoire en C était laborieux comparés à d'autres langages

  8. #8
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Citation Envoyé par vince85 Voir le message
    J'avais oublié à quel point gérer soi-même la mémoire en C était laborieux comparés à d'autres langages
    Ah ça, tu peux le dire…

  9. #9
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 800
    Points
    1 800
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    C'est pas la manière de programmer la plus brillante qui soit que d'avancer en disant "je fais ceci car ça marche même si je pige rien à ce que je fais". Surtout en C où un truc foireux peut marcher 15 jours et planter le 16° parce qu'on a rajouté un simple "printf()" ...
    Sans vouloir etre desagreable je te demanderai de relire CORRECTEMENT ce que j'ai dit. car justement je fais ce que je comprends et non ce que je comprend mal c'est pour ca queje dis que je fait ptr=funct plutot que funct(&ptr) car ca je maitrise pas. Merci de me relire

    je pense qu'il y a des gens sur ce forum qui cherche la petite bete pour attaquer les autres.
    ps: je parle sans colere.
    Petit lien vers mon premier jeux SDL2/C
    http://store.steampowered.com/app/72..._Soul_Of_Mask/
    la suite? ca vient,ca vient!

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    J'avais oublié à quel point gérer soi-même la mémoire en C était laborieux comparés à d'autres langages
    Je n'ai jamais trouvé cela laborieux. Au contraire, cela oblige le programmeur à bien coder et à ne pas se dire "tant pis si je code mal, sans même comprendre ce que je fais, et que y a plein de fuites de mémoire ou plein de dépassement de tableau, c'est pas grave, la machine virtuelle comblera mes lacunes à ma place". S'il existe autant de programmes buggués, ce n'est pas forcément à cause de l'informatique ni même du méchant O.S, c'est justement parce qu'on n'apprend plus trop la rigueur aux programmeurs (la programmation est censée suivre des règles, pour faire les choses bien), on leur apprend à mal coder et à se faire assister par des outils/langages souvent très coûteux en ressources qui feront le travail du programmeur à sa place. Ce n'est pas forcément un progrès AMHA...

    Le C fournit des fonctions qui ne laissent aucune ambigüité quant à savoir si elles ont échoué ou non, ce qui est notamment le cas de celles spécifiquement dédiées à l'allocation de mémoire. Par conséquent, il n'y a en principe rien qui puisse faire planter un programme correctement conçu.
    Après, forcément, il y a les cas de comportements indéfinis. Dépasser un tableau ne provoque pas forcément de crash. C'est un bug qui devient visible dès lors qu'une chose bizarre se produit. Mais cela ne doit pas remettre en question la rigueur qu'un programmeur doit avoir : toujours vérifier le code, se poser les bonnes questions, s'attacher à bien structurer son code, éviter les globales au maximum, etc.

    Que les choses soient clair : je ne te vise absolument pas en disant tout ça. C'est une réponse générale qui concerne, en fait, beaucoup de programmeurs d'une manière générale.

Discussions similaires

  1. Réponses: 7
    Dernier message: 23/12/2014, 14h34
  2. Réponses: 16
    Dernier message: 01/06/2008, 20h01
  3. Allocation dynamique d'un tableau de structures
    Par ryadh.naouar dans le forum C
    Réponses: 5
    Dernier message: 24/04/2008, 12h49
  4. Réponses: 4
    Dernier message: 08/05/2007, 20h10
  5. Allocation dynamique tableau dans structure
    Par chental dans le forum C
    Réponses: 2
    Dernier message: 03/08/2006, 09h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo