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 :

Rajout d'une structure (liste)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de m@tix
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    304
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 304
    Par défaut Rajout d'une structure (liste)
    Bonjour,

    J'ai créé jusque là un code consistant à répertorier différents objets, chacun contenu dans un maillon. En clair, voici un petit schéma:



    Jusque là, tout va bien, voici le code correspondant pour le moment:

    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
    #include <stdio.h>
     
    typedef struct objet {
    	int a;
    	int b;
    } un_objet;
     
    typedef struct maillon {
    	un_objet * infos;
    	struct maillon * suivant;
    } un_maillon;
     
    un_maillon *ajouterElement(un_maillon *le_maillon, un_objet *l_objet) {
    	un_maillon *nouveau_maillon = malloc(sizeof(un_maillon));
     
    	nouveau_maillon->suivant = NULL;
    	nouveau_maillon->infos = malloc(sizeof(un_objet));
    	nouveau_maillon->infos->a = l_objet->a;
    	nouveau_maillon->infos->b = l_objet->b;
     
    	if (le_maillon == NULL)
    		return nouveau_maillon;
    	else {
    		un_maillon *maillon_courant = le_maillon;
    		while (maillon_courant->suivant != NULL)
    			maillon_courant = maillon_courant->suivant;
    		maillon_courant->suivant = nouveau_maillon;
    		return le_maillon;
    	}
    }
     
    int main(void)
    {
    	un_maillon *le_maillon = NULL;
    	un_objet l_objet = { 12, 56 };
     
    	le_maillon = ajouterElement(le_maillon, &l_objet);
     
    	printf("%d\t%d", le_maillon->infos->a, le_maillon->infos->b);
     
    	return 0;
    }
    Seulement, on m'impose d'inclure dans mon code une structure liste supplémentaire définie ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct liste{
     
    	un_maillon * premier_maillon;
    	un_maillon * dernier_maillon;
    	un_maillon * maillon_courant; // pour se déplacer dans la liste sans perdre la place du premier maillon
     
    };
    On aurait alors un schéma comme le suivant:



    J'ai essayé d'implanter au code ci-dessus cette structure et les changements que cela entraîne, mais curieusement, je n'y parviens pas... Pouvez-vous me montrer svp?

    Merci d'avance!

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    A l'heure actuelle, tu utilises pour décrire ta liste un simple pointeur sur le premier maillon le_maillon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int main(void)
    {
    	un_maillon *le_maillon = NULL;
    Il s'agit de remplacer ce pointeur par une struct liste pour décrire ta liste.
    ajouterElement() va utiliser cette structure. Il n'a plus besoin de renvoyer la tête de liste, mais il peut utilement renvoyer un pointeur sur l'élément ajouté ou NULL en cas d'échec. Ceci permet de traiter une erreur possible dans l'allocation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(void)
    {
       struct liste liste = {NULL,NULL,NULL};
       un_maillon *le_maillon = NULL;
       un_objet l_objet = { 12, 56 };
       le_maillon = ajouterElement(&liste, &l_objet);
       if(le_maillon != NULL)
    ....
    ajouterElement() devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    un_maillon *ajouterElement(struct liste * liste , un_objet *l_objet) ;
    Dans son code, la variable de tête de liste (anciennement le_maillon) est maintenant liste->premier_maillon.
    Il faut ajouter la gestion de liste->dernier_maillon et (selon le cahier des charges) celle de liste->maillon_courant.

  3. #3
    Membre éclairé Avatar de m@tix
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    304
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 304
    Par défaut
    Merci pour la réponse!
    Avant que je ne tente de faire les modifications qui s'imposent dans le code, je souhaiterais comprendre ce que signifie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct liste liste = {NULL,NULL,NULL};
    Pourquoi trois "NULL"?

    Ensuite, étant donné qu'on me demande de faire une fonction pour initialiser une liste, je pense que la ligne de code ci-dessus va devenir inutile.. non? Concernant cette fonction, cela est-il acceptable?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int Initialiser_Liste(une_liste * la_liste)
    {
    	la_liste->premier_maillon = NULL;
    	la_liste->dernier_maillon = NULL;
     
    	return 0;
     
    }
    Si oui, comment l'inclure dans le main de test?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(void)
    {
       Initialiser_Liste(??);
       un_maillon *le_maillon = NULL;
       un_objet l_objet = { 12, 56 };
       le_maillon = ajouterElement(&liste, &l_objet);
       if(le_maillon != NULL)
    ....

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pourquoi trois "NULL"?
    Pour initialiser les trois pointeurs de struct liste à NULL.

    Ensuite, étant donné qu'on me demande de faire une fonction pour initialiser une liste,
    Deux options possibles :

    - la fonction initialise une liste déjà créée (initialiser les TROIS pointeurs):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Initialiser_Liste(struct liste* liste)
    {
        liste->premier_maillon = NULL;
        liste->dernier_maillon = NULL;
        liste->maillon_courant= NULL;
    }
     
    int main(void)
    {
       struct liste liste ; // la liste est créée ici
       Initialiser_Liste(&liste);
    ....
    - La fonction crée et initialise la liste (et on écrira en même temps une fonction pour détruire la liste ainsi créée). Elle doit donc être créée par allocation dynamique :
    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
    struct liste * Initialiser_Liste(void)
    {
       struct liste * liste =  malloc(......); // Créer
       if(liste != NULL)
      {	
           liste->premier_maillon = NULL;   // initialiser
            ...
       }
       return liste ;
    }
    void Detruire_Liste(struct liste * liste)
    {
    ...
    }
     
    int main(void)
    {
       struct liste liste * liste =  Initialiser_Liste() ; // la liste est créée ici
       if(liste != NULL)
       {
        ....
        Detruire_Liste(liste);
        liste = NULL; //par précaution
       }
        else
        {
           ....
         }
     
    ....

  5. #5
    Membre éclairé Avatar de m@tix
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    304
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 304
    Par défaut
    A première vue, je pense que la seconde solution serait la plus appropriée! J'ai complété ton code, en espérant ne pas m'être trompé..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct liste * Initialiser_Liste(void)
    {
       struct liste * liste = (struct liste *)malloc(sizeof(liste)); // Créer
       if(liste != NULL)
      {	
           liste->premier_maillon = NULL;   // initialiser
           liste->dernier_maillon = NULL;
           liste->maillon_courant = NULL;
     
       }
       return liste ;
    Par contre, est-il vraiment nécessaire de faire une fonction pour la détruire? Si oui pourquoi? Aussi, pourquoi avoir choisi de retourner la liste? Enfin, que retourne exactement cette fonction, et pourquoi?

    Ah, si, autre chose: la condition if(liste != NULL) est-elle vraiment indispensable? Après tout, vu que la liste vient tout juste d'être crée, à priori elle est vide non? Et puis même si ce n'était pas le cas (et justement j'ai envie de dire..), pourquoi ne pas l'initialiser?

  6. #6
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Le cast du malloc est inutile !
    Et il serait judicieux de ne pas appeler ta structure du même nom le pointeur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct liste * l_liste = malloc(sizeof(liste));
    Citation Envoyé par m@tix Voir le message
    Par contre, est-il vraiment nécessaire de faire une fonction pour la détruire? Si oui pourquoi? Aussi, pourquoi avoir choisi de retourner la liste? Enfin, que retourne exactement cette fonction, et pourquoi?

    Ah, si, autre chose: la condition if(liste != NULL) est-elle vraiment indispensable? Après tout, vu que la liste vient tout juste d'être crée, à priori elle est vide non? Et puis même si ce n'était pas le cas (et justement j'ai envie de dire..), pourquoi ne pas l'initialiser?
    Oui, toute mémoire allouée avec un malloc doit être libérée.

    Si tu ne retournes pas la liste, ta structure est créée dans la fonction et est accessible ... nul part :p
    D'où l'intérêt de renvoyer un pointeur sur cette structure
    Elle renvoie un pointeur sur 'struct liste'.

    Oui, la condition est nécessaire, parce qu'un malloc peut échouer et donc ton programme planterais
    La liste viens d'être créée oui, mais comme elle a été allouée dynamiquement par un malloc elle contient n'importe quoi, d'où la nécessité d'initialiser les champs à NULL. Tu peux aussi utiliser calloc à la place de malloc qui initialise la mémoire allouée à 0.

    Voilà, je crois que j'ai répondu à toutes tes questions

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/09/2009, 19h26
  2. Choix dans liste déroulante puis rajout d'une autre liste déroulante
    Par Nosti dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 01/02/2008, 17h50
  3. [AJAX] rajout d'une 3éme liste au tuto xmlhttprequest
    Par schevcheko dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 31/08/2007, 15h40
  4. Choix d'une structure pour une liste de tableau d'ansistring
    Par kurkaine dans le forum C++Builder
    Réponses: 5
    Dernier message: 11/05/2007, 07h36
  5. Récupérer une structure depuis une liste
    Par bit_o dans le forum GTK+ avec C & C++
    Réponses: 3
    Dernier message: 01/04/2007, 21h34

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