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 :

Type void * ... petite question !


Sujet :

C

  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut Type void * ... petite question !
    Bonjour,

    Toujours à titre d'exercice personnel, "j'essai" ... de me faire une liste chaînée simple mais générique. Ce que je voulais savoir, je voudrais dans une structure de ce type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct list {
       struct list * p_next;   /* Pointeur vers l'element suivant. */
       void * p_user_data;     /* Pointeur de type 'void' pour inserer les donnees
                                  de l'utilisateur. */
    } list;
     
    typedef list LIST_S;
    affecter au pointeur p_user_data une structure toute banale qui est définie dans le programme par l'utilisateur. Je pense que c'est possible mais apres, comment acceder aux données de cette structure en passant par la structure de la liste chaînée !

    Je tiens à préciser que pendant le malloc, on ne peut pas savoir s'il s'agira d'une structure, d'une tableau ou autre chose donc ca doit rester le plus théorique possible

    Enfin si c'est possible !
    Merci pour vos lumière

  2. #2
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    La liste chaînée n'a pas à connaître le type ni la taille de p_user_data.
    Le void * garantit le stockage d'une adresse c'est tout.
    C'est e programme 'utilisateur de la liste chaînée qui saura comment caster le p_user_data pour le manipuler correctement.

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Ok, ca c'est deja une bonne chose, maintenant, j'ai un peu de mal dans mon code, en fait pour le moment ma liste permet l'ajout d'un maillon en debut ou fin de liste mais je crois que je m'a gourré quelque part car j'ai l'impression que lorsque je veut ajouter un 2° maillon, ca boucle sans s'arreter . Voici mon code, en plus, quelqu'un pourra me dire ce qui va pas et ce qui pourrais etre amélioré ? :

    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
    60
    61
    62
    63
     
    int list_add_item (listg_s ** p, void * p_user_data, int add_type)
    {
       listg_s * p_new = NULL;
     
     
       /* Allocation en memoire du nouveau maillon de la liste. */
       p_new = (listg_s *) malloc (sizeof (listg_s) + sizeof (p_user_data));
     
       /* Si l'allocation echoue, on retourne NULL. */
       if (!p_new) {
          return (1);
       }
     
       /* Si 'p' vaut NULL alors on insere le premier element de liste et on fait
          pointer 'p' sur le nouvel element... */
       if (*p == NULL) {
          *p = p_new;
          p_new->p_user_data = p_user_data;
          p_new->p_next = NULL;
     
          return (0);
       }
     
       /* ...Sinon, on choisi le type de l'insertion. */
       switch (add_type) {
     
          /* Ajoute le maillon en fin de liste. */
          case ADD_AT_END :
             /* Recherche du dernier maillon. */
             while (*p) {
                *p = (*p)->p_next;
             }
     
             /* Ajout du nouveau maillon en fin de liste. */
             p_new->p_user_data = p_user_data;
             p_new->p_next = NULL;
             *p = p_new;
     
             break;
     
          /* Ajoute le maillon en debut de liste. */
          case ADD_AT_BEGIN :
             /* Recherche du premier maillon. */
             while (*p) {
                (*p)->p_next = *p;
             }
     
             /* Ajout du nouveau maillon en debut de liste. */
             p_new->p_user_data = p_user_data;
             p_new = *p;
     
             break;
     
          /* Par defaut on fait rien, on renvoie simplement 1 pour indiquer
             qu'une erreur c'est produite et qu'aucun traitement n'a eu lieu. */
          default :
             return (1);
     
       }
     
       return (0);
    }
    Merci tout plein, il faut vraiment que je progress à fond les ballons

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Ok, ca c'est deja une bonne chose, maintenant, j'ai un peu de mal dans mon code
    Ton code est sérieusement buggé et trop compliqué. Tu devrais dessiner ce que tu fais.
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
     
    #include <stdlib.h>
    #include <stdio.h>
    #include "ed/inc/sys.h"
     
    typedef struct list listg_s;
     
    struct list
    {
       listg_s *p_next;         /* Pointeur vers l'element suivant. */
       void const *p_user_data;     /* Pointeur de type 'void' pour inserer les donnees
                                       de l'utilisateur. */
    };
     
    enum
    {
       ADD_AT_END,
       ADD_AT_BEGIN,
       dummy
    };
     
    int list_add_item (listg_s ** const pp_head, void const *p_user_data, int add_type)
    {
       int err = 0;
       if (pp_head != NULL)
       {
          /* Allocation en memoire du nouveau maillon de la liste. */
          listg_s *p_new = malloc (sizeof *p_new);
     
          if (p_new != NULL)
          {
             /* initialisation du bloc nouvellement alloue. */
             p_new->p_user_data = p_user_data;
             p_new->p_next = NULL;
     
             if (*pp_head == NULL)
             {
                *pp_head = p_new, p_new = NULL;
             }
             else
             {
                /* ...Sinon, on choisi le type de l'insertion. */
                switch (add_type)
                {
     
                   /* Ajoute le maillon en fin de liste. */
                case ADD_AT_END:
                   /* Recherche du dernier maillon. */
                   {
                      listg_s *p = *pp_head;
     
                      while (p->p_next != NULL)
                      {
                         p = p->p_next;
                      }
     
                      /* Ajout du nouveau maillon en fin de liste. */
                      p->p_next = p_new, p_new = NULL;
                   }
     
                   break;
                   /* Insere le maillon en debut de liste. */
                case ADD_AT_BEGIN:
     
                   {
                      listg_s *p = *pp_head;
                      listg_s *p_next = p;
     
                      p_new->p_next = p_next;
                      *pp_head = p_new, p_new = NULL;
     
                   }
                   break;
     
                   /* Par defaut on fait rien, on renvoie simplement 1 pour indiquer
                      qu'une erreur c'est produite et qu'aucun traitement n'a eu lieu. */
                default:
                   free (p_new), p_new = NULL;
                   err = 1;
     
                }
             }
          }
          else
          {
             err = 1;
          }
          ASSERT (p_new == NULL);
       }
       else
       {
          err = 1;
       }
     
       return err;
    }
    /* fin du code generique */
     
     
    /* code applicatif (non generique) */
    static void print(listg_s const *const p_list)
       {
          listg_s const *p = p_list;
     
          while (p != NULL)
          {
             char const *s = p->p_user_data;
     
             printf ("%s\n", s);
     
             p = p->p_next;
          }
          printf ("\n");
       }
     
    static void onexit (void)
    {
       /* Dev-C++ trick ... */
       system ("pause");
    }
     
    int main (void)
    {
       listg_s *p_list = NULL;
       int ret;
     
     
       atexit (onexit);
     
       ret = list_add_item (&p_list, "Meuh", ADD_AT_END);
       ret = list_add_item (&p_list, "Gni", ADD_AT_END);
     
       print(p_list);
     
       ret = list_add_item (&p_list, "Blah", ADD_AT_BEGIN);
     
       print(p_list);
     
       return 0;
    }
    Penser aussi à libérer la chaine proprement. Pose des questions si tu ne comprends pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Meuh
    Gni
     
    Blah
    Meuh
    Gni
     
    Appuyez sur une touche pour continuer . . .

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Oui, je veut bien savoir où mon code etait buggé et les changement que tu as apporté :$, ca m'aiderais à comprendre car je ne veut pas bêtement recopier du code Je veut avancer dans mes connaissances en C, c'est pour ca que je me fait des exercices et celui-ci me parait etre un tres bon exercice

    En tous cas merci

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Oui, je veut bien savoir où mon code etait buggé et les changement que tu as apporté :$, ca m'aiderais à comprendre car je ne veut pas bêtement recopier du code Je veut avancer dans mes connaissances en C, c'est pour ca que je me fait des exercices et celui-ci me parait etre un tres bon exercice

    En tous cas merci
    Alors ne mélange pas les concepts de liste chainée et de généricité tant que l'un et l'autre ne sont pas maitrisés.

    Je recite le vieux sage (de mémoire):

    "Avant de faire compliqué, fait simple"

    Reprenons à la base.
    • Une liste chainée est une liste de noeuds (node) liés les uns aux autres par leurs références.
    • Un noeud est, par exemple une structure de données qui contient une référence à l'élément suivant, et éventuellement des données (ou une référence des données)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    STRUCTURE  NODE
    BEGIN
       STRUCTURE NODE next
       data
    END
    Pour définir une liste chainée, il faut une référence initale :
    à laquelle on donne la valeur 'référence non définie' (NIL) par défaut:
    C'est une façon d'exprimer que la liste est vide (pas de noeud, pas de données, pas d'élément suivant, rien, nada...)

    Pour ajouter un noeud, on va le créer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STRUCTURE NODE new_node := create_node()
    mettre les données :
    pour le moment, on indique qu'il n'y a pas d'élement suivant:
    Actuellement, ce noeud est 'libre'. Il n'est relié à aucune liste.

    On va maintenant le mettre dans la liste. Si liste est vide (la tete de liste vaut NIL), c'est simple, c'est par définition le premier élément. Il suffit donc de donner à la tete de liste la valeur du nouveau noeud:
    si la liste n'est pas vide, 2 cas sont possibles.

    Maintenant qu'on a un petit dessin, on voit qu'il n'est pas très compliqué d'écrire les algorithmes d'insertion.
    • Insertion en début de liste.
      - L'élément suivant du nouveau noeud devient l'ancienne tête de liste
      - La tête de liste devient le nouveau noeud.
      Ce qui donne :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
       
      new.node.next := head
      head := new_node
    • Insertion en fin de liste.
      - chercher le dernier élément (celui dont le suivant est NIL)
      - L'élément suivant du dernier élément devient le nouveau noeud.
      Ce qui donne :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
       
      STRUCTURE NODE node := head
       
      WHILE node.next <> NIL
      BEGIN
         node := node.next
      END
      node.next := new_node

    et voilà, c'est tout.

    Maintenant, tu codes ça en C avec une structure simple comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct node
    {
       struct node *p_next;
       int data;
    };
    On verra la généricité et d'autres astuces d'implémentation plus tard.

  7. #7
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    CA c'est de l'exercice, bien detaillé, en plus en point de vue algo, si c'est bien un exercice (je pense que oui quand meme) je m'y met dès demain (vu l'heure surtout, je veut faire ca a tete reposée). Je te mail mon code ou bien tu veut que je le post ici ?

    Fait attention, tu risque de devenir mon prof
    En tous cas merci pour ton post

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    CA c'est de l'exercice, bien detaillé, en plus en point de vue algo, si c'est bien un exercice (je pense que oui quand meme) .
    Je dirais plutôt que c'est un mini cours. L'exercice, il et à la fin!
    Je te mail mon code ou bien tu veut que je le post ici ?
    Poste le ici que tout le monde en profite (c'est le but).

  9. #9
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Bon, j'ai coupé court hein ! j'ai pas fait de fonctions ou autres, j'ai tout mis dans le main mais j'espère que j'ai bien fait .... te connaissans, je pense pas, j'en suis meme sur mais bon, c'est pour l'exemple au cas par cas surtout

    non non ..... m'engueuele pas
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    #include <stdio.h>
    #include <stdlib.h>
     
    struct node
    {
       struct node *p_next;
       int data;
    } node;
     
     
    int main (int argc, char *argv[])
    {
       /* Tete de liste. */
       struct node *head = NULL;
       struct node *new_node = NULL;
     
     
       /* Un premier noeud. */
       new_node = malloc (sizeof (struct node));
       if (new_node == NULL)
       {
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 10;
       new_node->p_next = NULL;
     
       /* Le nouveau noeud deviens la tete de liste car elle est vide. */
       head = new_node;
       new_node = NULL;
     
     
       /* Un second noeud. */
       new_node = malloc (sizeof (struct node));
       if (new_node == NULL)
       {
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 20;
       /* Le second noeud devient la premier. */
       new_node->p_next = head;
       head = new_node;
       new_node = NULL;
     
     
       /* Un troisieme noeud. */
       new_node = malloc (sizeof (struct node));
       if (new_node == NULL)
       {
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 30;
     
       /* Recherche du dernier noeud. */
       struct node *node = head;
       while (node->p_next != NULL)
       {
          node = node->p_next;
       }
       node->p_next = new_node;
       node = NULL;
       new_node = NULL;
     
     
       /* Affichage des donnees. */
       node = head;
       while (node != NULL)
       {
          fprintf (stdout, "%d\n", node->data);
          node = node->p_next;
       }
       node = NULL;
     
     
       /* Suppression de la liste. */
       node = head;
       struct node *temp = NULL;
       while (node != NULL)
       {
          temp = node->p_next;
          free (node);
          node = temp;
       }
     
     
       return (0);
    }

  10. #10
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Bon, j'ai coupé court hein ! j'ai pas fait de fonctions ou autres, j'ai tout mis dans le main mais j'espère que j'ai bien fait .... te connaissans, je pense pas, j'en suis meme sur mais bon, c'est pour l'exemple au cas par cas surtout
    Si c'est pas bon, c'est pas 'à cause de moi', mais plutôt parce que tu aurais pu faire une erreur. Par contre si cette erreur résulte d'une mauvaise explication, j'en assume la responsabilité.
    non non ..... m'engueule pas
    Ben si pour mettre les chances de ton coté, tu aurais au moins pu poster la version compilable!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    main.c: In function `main':
    main.c:20: parse error before '=' token
     
    main.c:59: warning: declaration of `node' shadows a global declaration
    main.c:9: warning: shadowed declaration is here
    main.c:12: warning: unused parameter `argc'
    main.c:12: warning: unused parameter `argv'
    Correction detaillée. Bien lire tout...
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    #include <stdio.h>
    #include <stdlib.h>
     
    /* -ed-
     * bien separer les donnees des liens.
     * Ca aide a la comprehension.
     */
    struct node
    {
       /* liens */
       struct node *p_next;
     
       /* donnees */
       int data;
     
    /* -ed-
       }node;
     
       Non. Tu ne veux pas definir une variable ici.
       Revoi la definition de structures...
     */
    };
     
    /* -ed-
     * ces parametres ne sont pas utilises...
     int main (int argc, char *argv[])
     */
    int main (void)
    {
       /* Tete de liste. */
       struct node *head = NULL;
       struct node *new_node = NULL;
     
       /* Un premier noeud. */
       /* -ed- Je dirais plutot 'Le' premier noeud */
     
       /* -ed- un 'struct' en trop */
       new_node = malloc (sizeof (struct node));
       /* -ed-
        * sizeof (struct node) est un peu complique a ecrire et a maintenir.
        * Je recommande d'utiliser le pointeur : sizeof *new_node.
        */
     
       if (new_node == NULL)
       {
          /* -ed-
           * 1 n'est pas une valeur portable pour exit() ou return from main().
           * Les valeurs portables sont 0, EXIT_FAILURE ou EXIT_SUCCESS.
           */
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       /* -ed- Pas 'insertion', mais 'copie' ou 'enregistrement' */
       new_node->data = 10;
     
       /* -ed- et ca, c'est pas de la donnee, c'est du lien par defaut */
       new_node->p_next = NULL;
     
       /* Le nouveau noeud deviens la tete de liste car elle est vide. */
       /* -ed- comment tu sais qu'elle est vide ? */
       head = new_node;
     
       /* Un second noeud. */
       new_node = malloc (sizeof (struct node));
       if (new_node == NULL)
       {
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 20;
       /* Le second noeud devient la premier. */
       /* -ed-
        * Ca depend de ton choix.
        * Insertion en tete ou en queue ? En tete, visiblement.
        */
     
       new_node->p_next = head;
       head = new_node;
     
       /* Un troisieme noeud. */
       new_node = malloc (sizeof (struct node));
       if (new_node == NULL)
       {
          exit (1);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 30;
     
       /* -ed-
        * Gni ? et le lien par defaut ?
        * p_next vaut n'importe quoi. C'est dangereux...
        */
       new_node->p_next = NULL;
       /* -ed- direct, sans reflechir, sans presumer de ce qui arrivera apres. */
     
       /* Recherche du dernier noeud. */
     
       /* -ed- Tout le monde n'a pas C99. : bloc */
       {
          struct node *node = head;
          while (node->p_next != NULL)
          {
             node = node->p_next;
          }
          node->p_next = new_node;
       }
     
       /* -ed- parentheses inutiles, return n'est pas une fonction. */
       return (0);
    }
    Ok. Les algos sont correts. Il manque quand même une visualisation (debug) et surtout une libération de la liste.

    Prochaine étape, faire la même chose (même noeud), mais avec une fonction d'ajout en tête, une fonction d'ajout en queue, une factorisation de la création du noeud.

    <edit>
    Avant de créer les fonctions, une étape intermédiaire permet de préparer le travail. Ca consiste a réorganiser les variables locales, de façon à en réduire la portée au minimum (même si il faiut ajouter des blocs et des définitions).
    </edit>

    Si on a un debug et une libération pour le même prix, c'est encore mieux!

  11. #11
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Erf, je suis bete, en fait l'erreur dans le premier malloc est effectivement de ma faut, c'est à cause d'un Ctrl-Z en trop, c'est corrigé de mon coté

    Apres la correction du premier malloc, voici le minimum de warning de mon compilo:
    list1.c: Dans la fonction « main »:
    list1.c:11: attention : unused parameter `argc'
    list1.c:11: attention : unused parameter `argv'

  12. #12
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Correction effective, j'ai rajouté un parcour et affichage de liste et suppression totale de liste, j'espère que ca t'ira

  13. #13
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Correction effective, j'ai rajouté un parcour et affichage de liste et suppression totale de liste, j'espère que ca t'ira
    C'est pas à moi qu'il faut que ça aille. C'est à toi!

    Relis bien les corrections que j'ai posté. Il y a encore quelques problèmes, mais le principe est correct.

    J'ai passé ton code au detecteur de mensonges, c'est OK. La libération de la mémoire est bien faite.

  14. #14
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Correction et amélioration d'apres les remarques de Emmanuel:

    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    #include <stdio.h>
    #include <stdlib.h>
     
    struct node
    {
       struct node *p_next;
       int data;
    };
     
     
    int main (void)
    {
       /* Tete de liste. */
       struct node *head = NULL;
       struct node *new_node = NULL;
     
     
       /* Un premier noeud. */
       new_node = malloc (sizeof *new_node);
       if (new_node == NULL)
       {
          exit (EXIT_FAILURE);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 10;
       new_node->p_next = NULL;
     
       /* Le nouveau noeud deviens la tete de liste car elle est vide. */
       head = new_node;
       new_node = NULL;
     
     
       /* Un second noeud. */
       new_node = malloc (sizeof *new_node);
       if (new_node == NULL)
       {
          exit (EXIT_FAILURE);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 20;
       /* Le second noeud devient la premier. */
       new_node->p_next = head;
       head = new_node;
       new_node = NULL;
     
     
       /* Un troisieme noeud. */
       new_node = malloc (sizeof *new_node);
       if (new_node == NULL)
       {
          exit (EXIT_FAILURE);
       }
     
       /* Insertion des donnees dans le nouveau noeud. */
       new_node->data = 30;
       new_node->p_next = NULL;
     
       /* Recherche du dernier noeud. */
       {
          struct node *node = head;
          while (node->p_next != NULL)
          {
             node = node->p_next;
          }
          node->p_next = new_node;
          node = NULL;
          new_node = NULL;
       }
     
     
       /* Affichage des donnees. */
       {
          struct node *node = head;
          while (node != NULL)
          {
             fprintf (stdout, "%d\n", node->data);
             node = node->p_next;
          }
          node = NULL;
       }
     
     
       /* Suppression de la liste. */
       {
          struct node *node = head;
          struct node *temp = NULL;
          while (node != NULL)
          {
             temp = node->p_next;
             free (node);
             node = temp;
          }
          head = NULL;
       }
     
     
       return EXIT_SUCCESS;
    }
    En tous cas encore merci, ca m'aide à y voir plus clair et à corriger quelques uns de mes defauts

  15. #15
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Correction et amélioration d'apres les remarques de Emmanuel:
    Ok. Il manque juste un petit head=NULL après la libération finale et de passer tous les pointeurs en p_xxx.

    Et aussi, revoir la terminologie dans les commentaires (dejà expliqué)

    Maintentant, on veut voir les fonctions.

  16. #16
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Pour les prefixes et suffixes, quand je code en generale je le fait. En fait, regulirement je jete un coup d'oeil sur ton site, pour voir les convention de nommages et autres...

    Maintenant j'attend avec impatience le suite de ton mini-cours

  17. #17
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Pour les prefixes et suffixes, quand je code en generale je le fait. En fait, regulirement je jete un coup d'oeil sur ton site, pour voir les convention de nommages et autres...

    Maintenant j'attend avec impatience le suite de ton mini-cours
    Euh à quel propos ?

    Moi, j'attend ton code avec les fonctions...

  18. #18
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Oui je sais ... mais bon, le temp que je mange, je prenne mon caf' quand meme hein !

  19. #19
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par CSoldier
    Oui je sais ... mais bon, le temp que je mange, je prenne mon caf' quand meme hein !
    Heure d'été, toussa... Il est 14:30!

    Au fait, l'heure du serveur semble être l'heure d'hiver...

  20. #20
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Héhé ouio c'est vrai, le forum est encore en heure d'hiver
    Bon, voici ce que j'ai deja fait ... si tu peut deja me corriger mais moi ca me convien ... n'etant pas encore un pro je n'attend que tes remarques, conseils, etc...

    < Rere ....Mise à jour ... avec fonction d'effacement d'un noeud ...>
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
     
    #include <stdio.h>
    #include <stdlib.h>
     
     
    typedef enum
    {
       ADD_AT_BEGIN,
       ADD_AT_END,
       REMOVE_FIRST,
       REMOVE_LAST,
       dummy
    } e_add_type;
     
     
    struct node
    {   
       /* Donnees */
       int data;
     
       /* Liens vers le noeud suivant. */
       struct node *p_next;
    };
     
     
    /* Fonction d'ajout d'un nouveau noeud dans la liste.
       On retourne 1 en cas d'echec sinon 0.*/
    int create_node (struct node **pp_head, int data, int add_type)
    {
       int err = 0;
     
       /* Allocation en memoire du nouveau noeud. */
       struct node *p_new = malloc (sizeof *p_new);
     
       if (pp_head != NULL)
       {
          /* Mise en place du nouveau noeud si l'allocation a reussie. */
          if (p_new != NULL)
          {
             p_new->data = data;
             p_new->p_next = NULL;
     
             /* S'il n'existe pas encore de noeud dans la liste, alors on
                defini le nouveau noeud en tant que premier de la liste. */
             if (*pp_head == NULL)
             {
                *pp_head = p_new;
                p_new = NULL;
             }
             else
             {
                switch (add_type)
                {
                   /* On ajoute le nouveau noeud en debut de liste. */
                   case ADD_AT_BEGIN :
                   {
                      p_new->p_next = *pp_head;
                      *pp_head = p_new;
                      p_new = NULL;
                   }
                   break;
     
                   case ADD_AT_END :
                   {
                      /* Recherche du dernier noeud de la liste. */
                      struct node *p_node = *pp_head;
     
                      while (p_node->p_next != NULL)
                      {
                         p_node = p_node->p_next;
                      }
     
                      /* Liaison nouveau noeud. */
                      p_node->p_next = p_new;
     
                      p_node = NULL;
                      p_new = NULL;
                   }
                   break;
                }
             }
          }
          else
          {
             /* Erreur memoire. */
             err = 1;
          }
       }
       else
       {
          /* pp_head vaut NULL donc on peut rien faire. */
          err = 1;
       }
     
     
       return err;
    }
     
     
    /* Fonction de suppression d'un element de fin ou debut de liste.
       On renvoie 1 en cas de problème sinon 0. */
    int remove_node (struct node **pp_head, int remove)
    {
       int err = 0;
     
     
       if (pp_head != NULL)
       {
          switch (remove)
          {
             /* On supprime le premier noeud de la liste. */
             case REMOVE_FIRST :
             {
                struct node *p_temp = (*pp_head)->p_next;
                free (*pp_head);
                *pp_head = p_temp;
                p_temp = NULL;
             }
             break;
     
             /* On supprime le dernier noeud de la liste. */
             case REMOVE_LAST :
             {
                /* Recherche du dernier noeud de la liste. */
                struct node *p_node1 = *pp_head;
                struct node *p_node2 = p_node1->p_next;
     
                while (p_node2->p_next != NULL)
                {
                   p_node1 = p_node2;
                   p_node2 = p_node1->p_next;
                }
     
                /* Supression du dernier noeud de la liste. */
                p_node1->p_next = NULL;
                free (p_node2);
             }
             break;
          }
       }
       else
       {
          /* pp_head vaut NULL, on sort */
          err = 1;
       }
     
     
       return err;
    }
     
     
    /* Fonction d'affichage de la liste. */
    void show_list (struct node const *p_head)
    {
       struct node const *p_node = p_head;
     
       while (p_node != NULL)
       {
          fprintf (stdout, "%d\n", p_node->data);
          p_node = p_node->p_next;
       }
       p_node = NULL;
     
       fprintf (stdout, "Fin de la liste !\n");
    }
     
     
    /* Supression de la liste. */
    void clear_list (struct node **pp_head)
    {
       struct node *p_node = *pp_head;
     
       while (p_node != NULL)
       {
          struct node *p_temp = p_node->p_next;
          free (p_node);
          p_node = p_temp;
       }
       p_node = NULL;
       *pp_head = NULL;
     
       fprintf (stdout, "La liste a ete supprimee !\n");
    }
     
     
    /* Fonction principale du programme. */
    int main (void)
    {
       struct node *p_head = NULL;
     
     
       /* Creation de trois noeuds.
          Le premier en debut de liste, le second en fin de liste
          et le troixième en debut de liste. */
       int err = create_node (&p_head, 10, ADD_AT_BEGIN);
     
       if (err)
       {
          exit (EXIT_FAILURE);
       }
       else
       {
          fprintf (stdout, "Noeud 1 ajoute !\n");
       }
     
       err = create_node (&p_head, 20, ADD_AT_END);
     
       if (err)
       {
          exit (EXIT_FAILURE);
       }
       else
       {
          fprintf (stdout, "Noeud 2 ajoute !\n");
       }
     
       err = create_node (&p_head, 30, ADD_AT_BEGIN);
     
       if (err)
       {
          exit (EXIT_FAILURE);
       }
       else
       {
          fprintf (stdout, "Noeud 3 ajoute !\n");
       }
     
     
       fprintf (stdout, "\n");
     
       /* Affichage de la liste. */
       fprintf (stdout, "Affichage de la liste :\n");
       show_list (p_head);
       fprintf (stdout, "\n");
     
     
       /* On retire le dernier noeud de la liste. */
       err = remove_node (&p_head, REMOVE_LAST);
     
       if (err)
       {
          exit (EXIT_FAILURE);
       }
       else
       {
          fprintf (stdout, "Le dernier noeud a ete supprime !\n");
       }
     
     
       /* Affichage de la liste. */
       fprintf (stdout, "Affichage de la liste :\n");
       show_list (p_head);
       fprintf (stdout, "\n");
     
     
       /* Suppression de la liste de la memoire. */
       fprintf (stdout, "Suppression de la liste :\n");
       clear_list (&p_head);
       fprintf (stdout, "\n");
     
     
       return EXIT_SUCCESS;
    }
    Resultat apres compilation sans erreurs et sans warning avec les options -Wall -W:
    Noeud 1 ajoute !
    Noeud 2 ajoute !
    Noeud 3 ajoute !

    Affichage de la liste :
    30
    10
    20
    Fin de la liste !

    Le dernier noeud a ete supprime !
    Affichage de la liste :
    30
    10
    Fin de la liste !

    Suppression de la liste :
    La liste a ete supprimee !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Petite question sur les types.
    Par carlesup3 dans le forum Caml
    Réponses: 8
    Dernier message: 07/07/2012, 20h43
  2. Petite question d'orientation insertion balises type Bbcode
    Par Sianobel dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 14/04/2010, 01h47
  3. petite question (type de retours covariants)
    Par Jabawock dans le forum C++
    Réponses: 6
    Dernier message: 21/08/2007, 09h06
  4. petite question sur les types de champs
    Par charlie koller dans le forum Débuter
    Réponses: 2
    Dernier message: 21/02/2007, 18h57
  5. question sur le type "void *"
    Par ChriGoLioNaDor dans le forum C++
    Réponses: 4
    Dernier message: 10/02/2006, 12h27

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