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 :

structures de données


Sujet :

C

  1. #1
    Futur Membre du Club
    Inscrit en
    Juin 2009
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 18
    Points : 7
    Points
    7
    Par défaut structures de données
    Bonjour,

    j'aurais besoin d'un peut d'aide si vous aviez une solution se serait geniale.

    voila concernant les listes chainées en langage c, sur lesquelles j'ai commencer a jeter un coup d'oeil, je trouve sa un peut casse pied de devoir reecrire chaque fonction de gestion (ajout/suppression de maillon, etc....) a chaque fois que la structure change (pour peut q'ont se rende compte un peut tard qu'il manque un champ.)

    donc l'idée que j'ai eu c'est d'utilisé les fonction de stdarg.h pour pallié a mon probleme.
    sauf que pas de bol sa le resout pas, j'arrive bien a faire une fonction qui prend "x" argument de type "f(x)" chacun mais concernant la strucure j'ai toujours le meme probleme, normale puisque mes pointeur de structure auquel j'attirbue les valeur en dépendent.

    donc l'hypothese de base pour resoudre mon probleme, a condition que se soit possible, c'est d'implanté un algo qui passe au champs suivant de ma structure (dans l'ordre de la declaration initiale) a chaque detection d'une nouvelle valeur.

    et une des premier soucis que je rencontre pour atteindre c'est objectif c'est de reussir a déclarer une structure de type tableau de champs.

    donc voila, c'est ma première question.

    en somme pour preciser peut etre un peut ma pensée, est il possible de creer une structure de type : par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void tableau[3];
    tableau[0]= int valeur;
    tableau[1]=char* data1;
    etc...
    ainis de suite, tant que necessaire. en somme je pense (ou meme la je fais carrement des plan sur la commete)
    qu'un tableau de pointeur sur mes variable de type en question serait adapté.

    mais encore une fois pas de bol j'ai pas reussi a ecrire la struct correpondante.

    si vous etes toujours là... merci de votre aide

  2. #2
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Bonjour gentil-personnage

    désolé, ne le prends pas mal, mais ton post, c'est un véritable charabia ! Tu mélanges tout et n'importe quoi.

    Les listes chainées : bien sur qu'il est impensable d'avoir/d'utiliser/d'écrire des listes qui ne traiteraient qu'un seul type de données. Généralement, les listes qu'on trouve dans diverses bibliothèques n'ont pas connaissance du type des données (je ne parle pas des pointeurs pour gérer le chaînage) qu'elles gèrent. Elles ont juste à connaître la taille de ces données. Jette un coup d'oeil aux types GList et GSList de Glib, la bibliothèque Gnome (par exemple).

    Stdarg.h ne te sera d'aucun secours : c'est fait pour gérer les arguments des fonctions qui ont un nombre d'arguments variable (comme la série des printf par exemple). Pour tes listes chainées, oublie !

    " ... c'est de reussir a déclarer une structure de type tableau de champs " : tu n'y arriveras pas, c'est impossible et ça n'a AUCUN sens ! Une structure (struct) c'est un type C en soi. Soit tu déclares un type structure, soit tu utilises des tableaux.

    Quant à déclarer "void tableau[3];", réfléchis 2 secondes. Void est un type un peu spécial pour signifier que ça n'a pas vraiment de type (ou que ça peut être n'importe quel type). Un compilo ne peut rien allouer du tout pour "tableau", car il ne connait pas le type des éléments et encore moins leur taille.

    Aussi, c'est très difficile de t'aider. Le seul conseil que je peux te donner c'est de bien mettre à plat ce que tu veux faire et, peut-être, de (re)voir les bases.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  3. #3
    Futur Membre du Club
    Inscrit en
    Juin 2009
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 18
    Points : 7
    Points
    7
    Par défaut
    je vais essayer d'etre plus claire
    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
     
    typedef struct element element;
    struct element
    {
        int val;
        struct element *nxt;
    }; 
    typedef element* llist;
     
     
    llist add_tete(llist liste, int val)
    {
        /* On crée un nouvel élément */
        element* nouvelElement = malloc(sizeof(element));
     
        /* On assigne la valeur au nouvel élément */
        nouvelElement->val = val;
     
        /* On assigne l'adresse de l'élément suivant au nouvel élément */
        nouvelElement->nxt = liste;
     
        /* On retourne la nouvelle liste, i.e. le pointeur sur le premier élément */
        return nouvelElement;
    }
    exemle j'utilise se code basique pour faire un ajout de maillon en tete de liste
    ce code est valable avec ma structure ci dessus.

    si ma structure change (admetton que je rajoute un tableau de char a l'interieur par exemple), je doit reecrire ma fonction de chainage en conséquence, pareil si ma strucure change de nom, etc...

    prenons le probleme dans l'autre sens, vers quelle solution dois je m'orienté pour creer des fonction de gestion de chaine (ajout en tete, en queue, suppression) sur lesquels le contenu, ou le nom de la strucure n'à aucune incidence (d'ou le void).

    des fonction faites pour creer/gerer/supprimer des liste avec tout type de structure.

    en gros pour faire simple est il possible de creer un tableau de pointeur sur divers elements.??

  4. #4
    Invité
    Invité(e)
    Par défaut
    Pour les listes de "n'importe quoi" tu vas probablement devoir utiliser une struct comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct list_el {
      list_el *next;
      void *data;
    }
    Tu construis alors ta liste comme on fait dans les livres (en manipulant les pointeurs next) et quand tu as besoin des données, tu utilises le pointeur data, que tu transtypes en ce qu'il te faut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ((montype *)data)->le_champ_que_je_veux;
    Maintenant, dans un tel système, la liste ne connait absolument pas le type de ses éléments, elle ne va donc pas pouvoir te dire en quoi transtyper data... Pour cela, soit tu ajoutes un champ type à list_el, soit tu fais une indirection dans data.

    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
     
    /*  avec champ type  */
     
    struct list_el {
      list_el *next;
      int type; /* 1 = entiers, 2=texte etc... */
      void *data;
    }
    /* ici faut lire type pour savoir en quoi caste data */
     
     
    /* avec indirection */
    struct type_el {
        int type;
        void *data;
    };
     
    struct list_el {
      list_el *next;
      type_el elem;
    }
    /*la faut lire elem.type, puis caster elem.data */
    Francois

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par fcharton Voir le message
    Maintenant, dans un tel système, la liste ne connait absolument pas le type de ses éléments, elle ne va donc pas pouvoir te dire en quoi transtyper data... Pour cela, soit tu ajoutes un champ type à list_el, soit tu fais une indirection dans data.
    Soit laisser la connaissance du type dans le code appelant et n'avoir aucune information de type dans la liste (sauf peut être une information de taille pour pouvoir prendre et rendre la responsabilité de la gestion de la durée de vie et de la mémoire des données contenues dans la liste).

    Dans le cas d'une liste uniforme (i.e. tous les éléments de la liste sont d'un même type), ce n'est pas hasardeux de supposer que le code appelant connaisse le type des données contenues dans la liste.
    Et c'est beaucoup plus réutilisable que le mécanisme consistant à sauvegarder l'information du type dans la liste, surtout quand tu commences à stocker des structures ou des enum dans la liste (avec la sauvegarde du type dans la liste, l'utilisation de la liste pour stocker une nouvelle structure nécessite de rajouter un nouveau type).

  6. #6
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    llist add_tete(llist liste, int val)
    {
        /* On crée un nouvel élément */
        element* nouvelElement = malloc(sizeof(element));
        ...
    Non, surtout pas. Tes fonctions de gestion de liste ne doivent pas connaître le type des éléments qu'elles gèrent si tu veux qu'elles soient génériques et qu'elles marchent pour toute nouvelle strcuture / type. Elles ne doivent connaître que la taille d'un élément de la liste et faire des copies "brutes" (memcpy) de ce qui est fourni.

    Tes fonctions de gestion de listes doivent définir leur propre type (à priori une structure) qui inclut les données à gérer fournies par l'appelant, sans présager de leur type, et le système de chaînage que tu auras défini (un pointeur "next" et un pointeur "previous" par exemple).


    Typiquement, un type element_liste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct _element_liste element_liste;
    struct _element_liste
    {
        void *data;   /* les donnees fournies qu'on NE veut PAS connaitre */
        element_liste *next;
        element_liste *previous
    };
    et un type liste qui peut ressembler à une structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct {
        unsigned int size_elt;
        element_liste *first;   /* premier element de la liste, NULL au debut */
        element_liste *last;   /* dernier element de la liste, NULL au debut */
    } liste;
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  7. #7
    Futur Membre du Club
    Inscrit en
    Juin 2009
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 18
    Points : 7
    Points
    7
    Par défaut
    merci pour vos reponse mais je pense pas qu'elle vont resoudre mon problement puisque de toute facon, meme si j'utilisais un void *data je serais obligé de faire un switch prenant en parametre mon int "type" pour caster le pointeur sur data en conséquence.

    ce qui ne ne fonctionne que dans les cas ou data reste un type de base. si data pointe sur une structure je devrais toujours acceder a mes champs par des pointeur de structure (struct->elem) et donc modifier mes fonction en conscéquence.

    l'idée de départ etait de chercher a creer un tableau de pointeur, pointant vers struct->elem et donc vers la valeur contenue par elem. tout sa de facon a pouvoir y acceder par un indice.

    mais bon, c'est vrai que c'est que plus j'y reflechis et moins je vois comment faire.


  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par gentil-personnage Voir le message
    merci pour vos reponse mais je pense pas qu'elle vont resoudre mon problement puisque de toute facon, meme si j'utilisais un void *data je serais obligé de faire un switch prenant en parametre mon int "type" pour caster le pointeur sur data en conséquence.

    ce qui ne ne fonctionne que dans les cas ou data reste un type de base. si data pointe sur une structure je devrais toujours acceder a mes champs par des pointeur de structure (struct->elem) et donc modifier mes fonction en conscéquence.
    Je pense qu'il y a une incompréhension.

    Dans le code appelant, oui tu manipules tes données avec leur type. En même temps, tu n'as pas le choix si tu veux travailler sur tes données, il faut bien les connaître. Et cela n'a aucun impact sur la gestion de la liste.

    Dans la gestion de la liste, non tu n'as plus besoin de connaître le type, donc tu n'as pas à caster le pointeur et tu n'as pas à accéder aux éléments de la structure. Tout le code de gestion de la liste ne manipules qu'une adresse générique (void*) et éventuellement une taille et une information de type (information qui n'est pas utilisé par la liste mais par le code appelant).
    A partir de là la liste est bien générique, que tu stockes un int, un double ou une structure quelconque, le code de gestion de la liste est le même et n'a pas a être modifié en fonction de ce que tu stockes dedans.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par gl Voir le message
    Dans le cas d'une liste uniforme (i.e. tous les éléments de la liste sont d'un même type), ce n'est pas hasardeux de supposer que le code appelant connaisse le type des données contenues dans la liste.
    Oui, mais ce cas là, c'est un peu le cas facile... La situation intéressante, à mon avis, c'est celui d'une liste où le type des éléments n'est connu qu'à l'exécution (par exemple, si on lit une donnée d'entrée qui peut etre du texte, des nombres, des tableaux, d'autres listes, n'importe quoi... C'est le vrai type de "liste hétérogène" (tous les autres ne sont que des raccourcis d'écriture).

    Il va alors falloir fournir au code appelant un moyen de déterminer le type des données qu'il lit (ne serait ce que pour savoir leur taille). La méthode la plus "propre" à mon avis est l'indirection (on rajoute un pointeur "type" entre la liste et la donnée), mais ca ralentira un peu le code...

    Gentil-personnage, si tu veux que les éléments de ta liste appartiennent à des types variables, mais que tu ne veux pas que la liste "le sache", tu ne peux échapper à un switch, ou une instruction similaire sur le type...

    Francois

  10. #10
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par fcharton Voir le message
    Oui, mais ce cas là, c'est un peu le cas facile... La situation intéressante, à mon avis, c'est celui d'une liste où le type des éléments n'est connu qu'à l'exécution (par exemple, si on lit une donnée d'entrée qui peut etre du texte, des nombres, des tableaux, d'autres listes, n'importe quoi... C'est le vrai type de "liste hétérogène" (tous les autres ne sont que des raccourcis d'écriture).
    Tout à fait.

    L'alternative que je proposais n'était qu'une autre alternative, avec ces avantages et inconvénients. Je ne prétendais pas qu'elle puisse s'appliquer dans tous les cas ni qu'elle soit toujours supérieurs aux autres possibilités.

    Citation Envoyé par fcharton Voir le message
    Il va alors falloir fournir au code appelant un moyen de déterminer le type des données qu'il lit (ne serait ce que pour savoir leur taille). La méthode la plus "propre" à mon avis est l'indirection (on rajoute un pointeur "type" entre la liste et la donnée), mais ca ralentira un peu le code...
    Si ce n'est que pour connaître la taille, autant stocker la taille alors.
    Stocker l'information du type va beaucoup plus loin que de pouvoir déterminer la taille de la donnée stockée et apporte beaucoup plus d'information.
    J'aurais même tendance à penser que les deux informations sont complémentaires et pourraient être toutes deux conservées (ce qui permet par ailleurs de n'avoir qu'un indicateur de type "tableau de X" et non un par taille dudit tableau.)

  11. #11
    Futur Membre du Club
    Inscrit en
    Juin 2009
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 18
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par gl
    Je pense qu'il y a une incompréhension.
    oui je le pense aussi, j'avoue moi meme ne pas avoir saisi toutes vos explications

    Citation Envoyé par fcharton Voir le message
    Oui, mais ce cas là, c'est un peu le cas facile... La situation intéressante, à mon avis, c'est celui d'une liste où le type des éléments n'est connu qu'à l'exécution (par exemple, si on lit une donnée d'entrée qui peut etre du texte, des nombres, des tableaux, d'autres listes, n'importe quoi... C'est le vrai type de "liste hétérogène" (tous les autres ne sont que des raccourcis d'écriture).
    meme si c'est vrai que le cas que tu propose est encore plus complexe, et d'autant plus interessant. l'idée de base etait simplement de coder une lib qui s'occupe de la "gestion standard" de mes listes sans avoir besoins de tout recoder a chaque changement de structure.

    en utilisant void *data qui pointe vers une struct, une boucle de lecture ne devrais pas fonctionné puisqu'elle m'obligerais a faire une liste principale, chainé avec les maillon next ou prev, chaque maillon ayant sont void *data qui pointerais vers la struct creer selon les besoins.

    or dans ce cas, par exemple une lecture de ma liste ne ce ferais plus de manière lineaire, mais en 2 temps :
    1/je me deplace d'un maillon de ma liste
    2/je passe par le pointeur data pour aller recuperer les infos de ma struct

    à mon sens le deplacement dans la chaine s'en trouve fortement compromis. tout comme les traitement en fonction de la valeur d'un struct->element.

    ma fois je suis a sec....

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par gentil-personnage Voir le message
    or dans ce cas, par exemple une lecture de ma liste ne ce ferais plus de manière lineaire, mais en 2 temps :
    1/je me deplace d'un maillon de ma liste
    2/je passe par le pointeur data pour aller recuperer les infos de ma struct

    à mon sens le deplacement dans la chaine s'en trouve fortement compromis. tout comme les traitement en fonction de la valeur d'un struct->element.
    Non, ca reste linéaire... La seule chose à ajouter, c'est un cast. En supposant que tu connaisses au préalable le type de tes éléments (ca c'est ce dont on causait avec gl), tu vas avoir quelque chose comme

    Dans le cas d'une liste avec pointeurs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct list_elem {
       list_elem *next;
       liste type *data;
    }
    tu avances en faisant
    elem->next;

    et tu lis un élément en faisant
    elem->data;

    Dans le cas d'une liste générique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct list_elem {
       list_elem *next;
       void *data;
    }
    tu avances toujours avec
    elem->next;

    mais pour lire un élément, tu fais
    ((list_elem*)(elem->data));

    y'a juste un cast en plus...

    Francois
    Dernière modification par Invité ; 05/07/2009 à 17h32.

  13. #13
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par gentil-personnage Voir le message
    or dans ce cas, par exemple une lecture de ma liste ne ce ferais plus de manière lineaire, mais en 2 temps :
    1/je me deplace d'un maillon de ma liste
    2/je passe par le pointeur data pour aller recuperer les infos de ma struct

    à mon sens le deplacement dans la chaine s'en trouve fortement compromis. tout comme les traitement en fonction de la valeur d'un struct->element.
    Euh, en te lisant j'ai des doutes. Que fais-tu exactement dans ton code ? Peux-tu fournir un exemple ?
    Rassures-moi, ce n'est pas la même fonction qui se déplace dans la liste (avec le pointeur next) et qui utilise les données ? La gestion de la liste est bien encapsulées et totalement indépendante d'un éventuel traitement des données ?

    Si tu veux un exemple de liste générique, je te conseille de lire cet article.

  14. #14
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Gentil-personnage, je t'imagine un peu perdu, alors, pour résumer ...

    Si tu veux un gestionnaire de listes qui puisse "encaisser" des changements dans tes types, de nouveaux types, etc...,

    1 : ne le lie pas aux types des éléments (ou seulement, et encore, à leur taille) : il gère des paquets d'octets, point barre. L'appelant te les a fournis, il sait ce que c'est, à lui de s'en ... dépatouiller quand tu lui renvoies

    2 : ne demande pas l'impossible à ton gestionnaire : faire afficher les éléments de la liste par le gestionnaire c'est trop demander (il doit connaître le type : printf ... %s ? %d ? etc...)

    3 - pour le moment, traite le cas des listes ayant des éléments de même type (tu résoudras 95 (99 ?) % des cas)

    Pour illustrer tout ça, j'ai pondu quelques lignes qui permettent de gérer des piles FILO (First In, Last Out, c'est la pile d'hebdos que tu stockes les uns sur les autres, que tu dépiles par le dessus). Les listes c'est un chouia plus compliqué mais l'idée y est.

    Mon main l'utilise aussi bien pour des entiers que pour des structures. J'ai pris aussi l'option de TOUT recopier ce qu'on me transmet (et je n'ai pas traité les erreurs).


    filo.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
    23
    24
    25
    26
    27
    28
    #include <stdio.h>
    #include <stdlib.h>
     
    #ifndef _FILO_
    #define _FILO_
     
    typedef struct _filo_elt filo_elt;
     
    struct _filo_elt
    {
        void        *data;  /* les donnees */
        filo_elt    *under; /* l'element en dessous */
     
    };
     
    typedef struct _filo
    {
        unsigned int size;  /* taille des elements */
        filo_elt *top;      /* le haut de la pile */
     
    } filo;
     
    filo *filo_new(unsigned int size);
    filo *filo_push(filo *aFilo,void *value);   /* ajoute un element en haut de la pile */
    void *filo_pull(filo *aFilo);               /* retire l'element du haut de la pile */
    void  filo_close(filo **aFilo);
     
    #endif
    filo.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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "filo.h"
     
     
    filo *filo_new(unsigned int size)
    {
        filo *aFilo = malloc(sizeof(filo)); /* allocation pour une nouvelle pile filo */
        aFilo->size = size;                 /* je memorise la taille */
        aFilo->top  = NULL;                 /* la pile est vide */
        return aFilo;
    }
     
    filo *filo_push(filo *aFilo,void *value)
    {
        filo_elt *elt = malloc(sizeof(filo_elt));   /* allocation pour nouvel element */
        elt->data = malloc(aFilo->size);            /* allocation pour copier les donnees */
        memcpy(elt->data,value,aFilo->size);        /* je recopie les donnees transmises (type ???) */
        elt->under = aFilo->top;                    /* suivant = actuel haut de pile, eventuellement NULL */
        aFilo->top = elt;                           /* element ajoute = nouveau haut de la pile */
        return aFilo;
    }
     
    void *filo_pull(filo *aFilo)
    {
        filo_elt *top  = aFilo->top;    /* je memorise le haut de la pile */
        void     *data;                 /* les donnees a retourner */
        data       = top ? top->data  : NULL;
        aFilo->top = top ? top->under : NULL;
        if (top) free(top); /* je libere, si non NULL, l'ancien haut de la pile, desormais inutile */
        return data;        /* je renvoie les donnees (ou NULL) */
    }
     
    void filo_close(filo **aFilo)
    {
        while (aFilo->top)
        {
            filo_elt *top = (*aFilo)->top; /* je "retiens" le haut de la pile */
            (*aFilo)->top = top->under;    /* nouveau haut de la pile */
            free(top);                  /* je libere l'ancien haut de la pile */
        }
       free(*aFilo);
    }
    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
    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "filo.h"
     
    typedef struct {
        char pseudo[32];
        int annee_inscription;
    } membre;
     
     
    #define NB_INT  5
    #define NB_MEMBRE   2
     
    int main(int argc,char *argv[])
    {
        int   *tab_int;
        int   *ptr_int;
        filo  *filo_int = filo_new(sizeof(int));
     
        membre *tab_membre;
        membre *ptr_membre;
        filo   *filo_membre = filo_new(sizeof(membre));
     
        int i,count;
     
        tab_int = malloc(NB_INT*sizeof(int));   /* j'alloue mon tableau d'entiers */
        for (i=0;i<NB_INT;i++) tab_int[i] = i;  /* je le remplis avec 0, 1, ... 4) */
     
        tab_membre = malloc(NB_MEMBRE*sizeof(membre));      /* analogue avec mon tableau de membres */
        strcpy(tab_membre[0].pseudo,"gentil-personnage");
        tab_membre[0].annee_inscription = 2009;
        strcpy(tab_membre[1].pseudo,"plxpy");
        tab_membre[1].annee_inscription = 2009;
     
        /* je remplis mes deux piles */
        for (i=0;i<NB_INT;i++)    filo_push(filo_int,tab_int+i);
        for (i=0;i<NB_MEMBRE;i++) filo_push(filo_membre,tab_membre+i);
     
        /* je reinitialise mes tableaux (pour montrer que ce sont les piles qui ont copie mes donnees) */
        memset(tab_int,0,NB_INT*sizeof(int));
        memset(tab_membre,0,NB_MEMBRE*sizeof(membre));
     
        fprintf(stdout,"depilage table d'entiers\n");
        count = 1;
        while (ptr_int = filo_pull(filo_int)) {
            fprintf(stdout,"position %d : %d\n",count,*ptr_int);
            free(ptr_int);
            count++;
        }
     
        fprintf(stdout,"depilage table membres\n");
        count = 1;
        while (ptr_membre = filo_pull(filo_membre)) {
            fprintf(stdout,"position %d : %s (%d)\n",count,ptr_membre->pseudo,ptr_membre->annee_inscription);
            free(ptr_membre);
            count++;
        }
    }
    le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    plx@sony:~/pile$ ./main
    depilage table d'entiers
    position 1 : 4
    position 2 : 3
    position 3 : 2
    position 4 : 1
    position 5 : 0
    depilage table membres
    position 1 : plxpy (2009)
    position 2 : gentil-personnage (2009)
    plx@sony:~/pile$
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  15. #15
    Futur Membre du Club
    Inscrit en
    Juin 2009
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 18
    Points : 7
    Points
    7
    Par défaut salut
    je voulais juste vous remercier pour le temps que vous avez pris a me repondre.

    si j'ai bien compris vos explications, l'idée etait plus de creer des fonction de chainage - generique- appelée a l'interieur de fonction d'ecriture/lecture/travail sur valeur.

    en fait je pense que j'avais visé un objectif trop haut je vais donc revoir mes ambitions a la baisse.(effectivement je cherchais bien a creer des fonction completement multitaches capable de chainées/lire/ecrire/traité n'importe quel structure).

    je vais donc tenter de "ruminer" tout les concept liés avant d'y revenir.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment créer une structure de donnée dynamiquement ?
    Par Beaunico dans le forum Langage
    Réponses: 9
    Dernier message: 24/01/2006, 09h34
  2. Aide pour diagramme de structure des données
    Par DeezerD dans le forum Décisions SGBD
    Réponses: 4
    Dernier message: 04/12/2004, 19h10
  3. Méta-Programmation - [ structures de données ]
    Par Dam)rpgheaven dans le forum C++
    Réponses: 3
    Dernier message: 03/12/2004, 19h38
  4. Structure des données en retour d'un DBExtract ?
    Par mikouts dans le forum XMLRAD
    Réponses: 4
    Dernier message: 24/01/2003, 15h15
  5. Structure de données de type "RECORD"
    Par chaours dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 30/09/2002, 17h10

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