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 :

création difficile d'une structure


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut création difficile d'une structure
    Bonjour,

    Voilà j'ai un petit soucis concernant une structure, je souhaiterais ajouter un tableau de chaînes de caractères.

    Voici ma structure dans mon fichier.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef TEST_H_INCLUDED
    #define TEST_H_INCLUDED
     
     
    typedef struct tab
    {
        char **table;
        int len;
    } tab;
     
    void ajouter(tab *tableau, char *ligne);
     
    #endif
    J'ai ensuite créer une fonction ajouter dans mon fichier.c

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void ajouter(tab *tableau, char *ligne)
    {
        tableau->table[tableau->len] = ligne;
        tableau->len++;
    }
    Ma fonction pour créer un nouveau tableau

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tab *create()
    {
        tab *new = malloc(sizeof(tab));
        new->len = 0;
        return new;
    }
    et un main pour tester

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(void)
    {
        tab *T = create();
        ajouter(T, "Bonjour");
        afficher(T);
        return 0;
    }
    Apparemment ça bug dans la fonction ajouter, j'ai pas de message d'erreur (ça compile), mais avec gdb, ça stoppe dans la fonction.

    Bref il doit y avoir un soucis dans la syntaxe ou une incompréhension de ma part

    Je vous remercie pour votre aide...

    P.S Il y a sans doute une autre façon de faire ce genre d'exercice, mais je m'entraîne aux structures.

    P.S2 La syntaxe me paraissant la plus logique était

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau->table[tableau->len][] = ligne;
    Mais le compilateur n'a pas aimé

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Salut,

    partons de ta structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #ifndef TEST_H_INCLUDED
    #define TEST_H_INCLUDED
     
     
    typedef struct tab
    {
        char **table;
        int len;
    } tab;
     
    #endif
    Elle contient len, je suppose la longueur en char* de table, et table que tu vas utiliser comme un tableau de char*.
    Tu crées une fonction d'allocation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    tab *create()
    {
        tab *new = malloc(sizeof(tab));
        new->len = 0;
        return new;
    }
    Il te manque, a priori, l'allocation de table.
    Je dis a priori car tu peux gérer ça dans la fonction d'ajout.

    Donc si tu veux ajouter une chaine il te faut faire de la place dans table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    if (tab->len==0) {
      // le premier élément crée la table
      tab->table= malloc(sizeof(char*));
      // on ajoute l'élément
      tab->table[0] = strdup(ligne);
      tab->len=1;
    } else {
      // on étend table
      tab->table=realloc(tab->table,(tab->len+1)*sizeof(char*));
      // on ajoute l'élément
      tab->table[tab->len] = strdup(ligne);
      tab->len++;
    }

    Il faut évidemment rajouter la gestion des erreurs d'allocations, ce code est tapé à la volée et peut contenir des erreurs.

    Ce n'est pas très optimisé de réallouer par morceau de 1 ... tu peux essayer de garder une capacité en plus de la longueur. Tu pourrais allouer par tranches plus grandes que 1.
    J'utilise strdup, cela permet de rendre les données indépendantes de la source, au lieu de faire un copie de pointeur il y a une copie de contenu dans un nouvel espace.
    N'oublie pas d'implémenter la libération de la mémoire (vachement important quand même !).

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 308
    Billets dans le blog
    5
    Par défaut
    Pour commencer la déclaration de la structure n'est pas conforme. Ce qui est en rouge est de trop :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct tab
    {
        char **table;
        int len;
    } tab;

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut
    Elle contient len, je suppose la longueur en char* de table, et table que tu vas utiliser comme un tableau de char*.
    Ah je t'arrêtes tout de suite, len est la longueur de tab et non de table

    @gerald3d

    Merci j'ai retiré mais la même erreur persiste

    Je place le code en entier après modification, il doit pas y avoir grand chose.

    Ma modification (j'ai tenté), le rajout de la fonction strcpy dans la fonction ajouter

    test.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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "test.h"
     
    void ajouter(tab *tableau, char *ligne)
    {
        strcpy(tableau->table[tableau->len], ligne); /* Modification */
        tableau->len++;
    }
     
    void afficher(tab *tableau)
    {
        int i=0;
        for(; i<tableau->len; i++)
        {
            printf("ligne --> %s", tableau->table[i]);
        }
        tableau = NULL;
        free(tableau);
    }
     
    tab *create()
    {
        tab *new = malloc(sizeof(tab));
        new->table = NULL;
        new->len = 0;
        return new;
    }
     
    int main(void)
    {
        tab *T = create();
        char test[] = "Bonjour";
        ajouter(T, test);
        afficher(T);
        return 0;
    }
    test.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
    #ifndef TEST_H_INCLUDED
    #define TEST_H_INCLUDED
     
     
    typedef struct
    {
        char **table;
        int len;
    } tab;
     
    void ajouter(tab *tableau, char *ligne);
    void afficher(tab *tableau);
    tab *create();
     
     
    #endif

  5. #5
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Ah je t'arrêtes tout de suite, len est la longueur de tab et non de table

    Hum, je pense que tu te représentes mal les choses. Un tab a une longueur constante la taille d'un entier plus la taille d'un pointeur ; len est bien le nombre de chaine contenue dans table.
    À moins que tu ne cherches à créer un tableau de tab ?

    Quelle genre de structure essayes-tu de créer ?

    { {"bonjour",0}, {"comment",1} , {"vas",2}, {"tu",3} }
    ou
    { {"bonjour", "comment", "vas", "tu"} , 4}

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut
    Ha j'ai trouvé mon erreur, j'ai effectivement oublié d'allouer de la mémoire pour mon table, mais dans la fonction ajouter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau->table[tableau->len] = malloc(strlen(ligne) * sizeof(char));
    Du coup ça fonctionne nickel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void ajouter(tab *tableau, char *ligne)
    {
        tableau->table[tableau->len] = malloc(strlen(ligne) * sizeof(char));
        strcpy(tableau->table[tableau->len], ligne);
        tableau->len++;
        free(tableau->table[tableau->len]);
    }

  7. #7
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut
    Hum, je pense que tu te représentes mal les choses. Un tab a une longueur constante la taille d'un entier plus la taille d'un pointeur ; len est bien le nombre de chaine contenue dans table.
    À moins que tu ne cherches à créer un tableau de tab ?
    Bah en fait je recherche à faire une liste de chaînes de caractères

  8. #8
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 308
    Billets dans le blog
    5
    Par défaut
    Un autre moyen serait d'essayer de construire une liste chaînée. Ca va t'obliger à manipuler les pointeurs pour la créer et la gérer.
    Une fois qu'elle est opérationnelle tu peux t'en servir de brique pour construire ton application actuelle.

    Ca reste un très bon exercice pour appréhender les pointeurs.

  9. #9
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void ajouter(tab *tableau, char *ligne)
    {
        tableau->table[tableau->len] = malloc(strlen(ligne) * sizeof(char));
        strcpy(tableau->table[tableau->len], ligne);
        tableau->len++;
        free(tableau->table[tableau->len]);
    }
    Deux erreurs en gras :
    la première tu oublies le 0 terminal (classique ) La chaine "bonjour" est de longueur 7 mais prend 8 octets {'b','o','n','j','o','u','r',0} -> il faut toujours réserver strlen + 1

    tu libères de la mémoire que tu viens d'allouer (ou presque, voir le len++) -> je ne pense pas que cela soit ce que tu désires.

Discussions similaires

  1. Réponses: 0
    Dernier message: 04/04/2012, 19h08
  2. Réponses: 0
    Dernier message: 26/07/2011, 14h20
  3. Création d'une structure dynamique
    Par jbat dans le forum API, COM et SDKs
    Réponses: 17
    Dernier message: 14/04/2008, 15h55
  4. Création d'un vecteur à partir d'une structure
    Par lilyla dans le forum MATLAB
    Réponses: 4
    Dernier message: 13/02/2008, 13h45
  5. Réponses: 20
    Dernier message: 11/07/2006, 17h11

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