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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent
    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
    Par défaut
    Citation Envoyé par CSoldier
    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...
    Je dois partir... Je reviens vers 18:00 tu peux faire une pause !

  2. #2
    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 : 48
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Oki no prob
    Bon pour la pause j'ai attendu car j'ai pas pu m'empecher de finir donc j'ai mis mon post de mon dernier code (avec fonctions) à jour
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Expert éminent
    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
    Par défaut
    Citation Envoyé par CSoldier
    Oki no prob
    Bon pour la pause j'ai attendu car j'ai pas pu m'empecher de finir donc j'ai mis mon post de mon dernier code (avec fonctions) à jour
    OK. C'est très bien. Quelques remarques légères :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    enum
    {
       ADD_AT_BEGIN,
       ADD_AT_END,
     
       /* -ed-
        * C99 accepte ca, mais pas C90. Pour etre portable, le dernier
        * element ne doit pas etre suivi d'une ','.
        */
       ADD_NB
    };
     
    /* -ed-
     * Etant assez maniaque du rangement
     * (en matiere de programmation, parce que mon bureau, c'est pas ca!),
     * j'aurais probablement defini un typedef enum ... (eADD, add_e, ADD ...)
     */
     
    struct node
    {
       /* Donnees */
       int data;
     
       /* Liens vers le noeud suivant. */
       struct node *p_next;
    };
     
    /* Fonction d'ajout d'un nouveau noeud en fin de liste.
       On retourne 1 en cas d'echec sinon 0. */
     
    /* -ed- le commentaire est faux. Cette fonction fait plus que ca... */
     
    int create_node (struct node **pp_head, int data, int add_type)
    {
       int err = 0;
     
    /* -ed-
     * Attention. Si pp_head vaut NULL, on ne peut rien faire...
     * Idem dans toutes les fonctions.
     */
       if (pp_head != NULL)
       {
    /* -ed-
       struct node *p_new = NULL;
     
       p_new = malloc (sizeof *p_new);
     
       * pourquoi ne pas combiner definition et initialisation ?
     */
     
          /* Allocation en memoire du nouveau noeud. */
          struct node *p_new = malloc (sizeof *p_new);
     
          /* 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
          {
             /* err memoire */
             err = 1;
          }
       }
       else
       {
          /* pp_head == NULL */
          err = 1;
       }
     
       return err;
    }
     
    /* Fonction d'affichage de la liste. */
     
    /* -ed-
     
       void show_list (struct node *p_head)
     
       * l'affichage est cense ne faire que de la lecture.
       * On peut donc ajouter 'const'.
     */
     
    void show_list (struct node const *p_head)
    {
    /* -ed-
       struct node *p_node = p_head;
     
       * evidemment, le pointeur doit etre du meme type...
     */
       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, "La liste a ete parcourue avec succes !\n");
    }
     
     
    /* Supression de la liste. */
    void clear_list (struct node **pp_head)
    {
       struct node *p_node = *pp_head;
     
    /* -ed-
     * p_temp n'existe que dans la boucle.
     * Inutile de le definir en dehors de celle-ci.
     
       struct node *p_temp = NULL;
       
    */
       while (p_node != NULL)
       {
          struct node *p_temp = p_node->p_next;
          free (p_node);
          p_node = p_temp;
       }
       p_node = NULL;
     
    /* -ed-
     * il manque une action importante
     * (sinon, ce n'était pas la peine de passer l'adresse du pointeur) :
    */
       *pp_head = NULL;
     
       fprintf (stdout, "La liste a ete supprimee!\n");
    }
     
    /* Fonction principale du programme. */
    int main (void)
    {
    /* -ed-
       int ret;
     
     * la fonction retourne une erreur. Donc autant appeler la variable err.
     * Ca sous-entend 0=OK 1=ERR.
     * D'autre pasrt, mieux vaut combiner definition et initialisation.
     */
     
       struct node *p_head = NULL;
     
       /* -ed- eviter les accents et les fautes d'orthographe... */
     
       /* Creation de trois noeuds.
          Le premier en debut de liste, le second en fin de liste
          et le troisieme en debut de liste. */
     
    /* -ed-
       if ((ret = create_node (&p_head, 10, ADD_AT_BEGIN)) != 0)
       
     * Eviter de combiner affectation et test quand ce n'est pas necessaire
     * (avec un if(), ce n'est jamais necessaire, avec un while(), faut voir).
     
     */
       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");
     
       /* Suppression de la liste de la memoire. */
       fprintf (stdout, "Suppression de la liste :\n");
       clear_list (&p_head);
       fprintf (stdout, "\n");
     
       return EXIT_SUCCESS;
    }
    Comme tu peux le constater, ce codage souffre de 2 points faibles:
    • Le passage du paramètre p_head n'est pas clair (avec &, sans &...)
    • Le tems d'acces au dernier element augmente avec la taille. L'opération d'jout en fin de liste devient donc de plus en plus couteuse.

    C'est pourquoi je recommande d définir une structure 'liste' qui contient à la fois le pointeur de tête et un nouvau pointeur : le pointeur de queue (sur le dernier element). Ca permet d'accélerer considérablement l'ajout d'un élément.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct list
    {
       struct node *p_head;
       struct node *p_tail;
    }
    Il faudrait aussi traiter les cas 'retirer en tête' et retirer en queue'...

  4. #4
    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 : 48
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Ok ! Merci pour tes commentaires, ca m'aide bicoup à devenir meilleur mais une chose :

    Comme tu peux le constater, ce codage souffre de 2 points faibles:
    • Le passage du paramètre p_head n'est pas clair (avec &, sans &...)
    Tu propose une autre approche ?

    PS : Nouvelle MàJ du code avec une fonction d'effacement du premier et dernier noeud, y'a surement quelque chose à optimiser je pense car je trouve que c'est encore un peu le foutoir
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Expert éminent
    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
    Par défaut
    Citation Envoyé par CSoldier
    Comme tu peux le constater, ce codage souffre de 2 points faibles:
    • Le passage du paramètre p_head n'est pas clair (avec &, sans &...)
    Tu propose une autre approche ?
    Oui, le struct list que j'ai expliqué après...
    PS : Nouvelle MàJ du code avec une fonction d'effacement du premier et dernier noeud, y'a surement quelque chose à optimiser je pense car je trouve que c'est encore un peu le foutoir
    Quelques remarques:
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef enum
    {
       ADD_AT_BEGIN,
       ADD_AT_END,
       REMOVE_FIRST,
       REMOVE_LAST,
       dummy
    } e_add_type;
     
    /* -ed-
     * le nom de l'enum ne correspond plus a la liste des fonctions.
     
     * je ferais comme ca (NA pour 'Node Action') :
     
    typedef enum
    {
       NA_ADD_AT_BEGIN,
       NA_ADD_AT_END,
       NA_REMOVE_FIRST,
       NA_REMOVE_LAST,
       NA_NB
    }
    node_act_e;
     
     * ou alors 2 listes, puisque ce sont des parametres qui concernent 2 fonctions
     * differentes. LEs valeurs peuvent de ADD_xx et REMOVE_xx peuvent etre les
     * memes... C'est ce genre de refexion faite en debut de projet qui permet
     * un meilleur decoupage, une meillleure approche fonctionelle...
     
    typedef enum
    {
       ADD_AT_BEGIN,
       ADD_AT_END,
       ADD_NB
    } add_type_e;
     
    typedef enum
    {
       REMOVE_FIRST,
       REMOVE_LAST,
       REMOVE_NB
    } remove_type_e;
     
    */
     
    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.*/
    /* -ed-
    int create_node (struct node **pp_head, int data, int add_type)
     
     * maintenant, il faut etre logique. On ne cree pas un type pour ne
     * pas s'en servir. Evidemment, un tel nom dans la fonction 'remove'
     * ca va faire desordre...
     */
    int create_node (struct node **pp_head, int data, e_add_type add_type)
    {
       int err = 0;
     
       /* Allocation en memoire du nouveau noeud. */
     
       /* -ed-
       struct node *p_new = malloc (sizeof *p_new);
        * Illogique. Tu ne pas pas creer un block si pp_head vaut NULL...
        */
     
       if (pp_head != NULL)
       {
          /* -ed-
           * deplace...
           * Par construction, ca evite une fuite memoire...
           */
          struct node *p_new = malloc (sizeof *p_new);
     
          /* 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;
     
                      /* -ed-
                       * il n'est pas indispensable de mettre ce pointeur a NULL.
                       * (car sa est portee limitee au prochain } )
                       */
                      p_node = NULL;
     
                      /* -ed-
                       * Mais as-tu compris pourquoi je mettais celui-ci
                       * a NULL ?
                       */
                      p_new = NULL;
                   }
                   break;
     
                   /* -ed-
                    * Maintenant que la variable de selection est typee,
                    * mon compilateur me sort des warning interessant qui
                    * font reflechir sur la pertinence du choix de la liste
                    * de constantes et de ma proposition d'avoir 2 listes
                    * separees...
     
    main.c: In function `create_node':
    main.c:127: warning: enumeration value `REMOVE_FIRST' not handled in switch
     
    main.c:127: warning: enumeration value `REMOVE_LAST' not handled in switch
    main.c:127: warning: enumeration value `dummy' not handled in switch
     
                    */
                }
             }
          }
          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. */
     
    /* -ed-
     * ATTENTION : danger potentiel.
     * 'remove()' est une fonction du C standard definie dans <stdio.h>.
     * Il est peu recommande' d'utiliser ce mnemonique pour autre chose.
     * En l'occurence, la fonction 'remove()' est masquee
     * (shadowed, inaccessible)
     *
     *
     * Comme precedement, utiliser le type enum...
     */
    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;
                /* -ed-
                 * Gni? Y'avait des horreurs comme ca dans mon code ?
                 * Non. Pourquoi, parce que j'utilise un pointeur local
                 * 'p_head' ... sinon, l'algo est correct.
                 */
     
                free (*pp_head);
                *pp_head = p_temp;
     
                /* -ed-
                 * ca, tu le vires... on ne risque pas de le reutiliser
                 * ailleurs, la } est la...
                 */
                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;
                /* -ed- et si pnode_1 , c'est a dire *pp_head vaut NULL ? */
     
                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);
     
                /* -ed-
                 * as-tu reflechi a cet algo en langage parle' puis
                 * algorithmique comme je l'avais fait pour les premiers ?
                 * Je ne crois pas...
                 */
             }
             break;
          }
       }
       else
       {
          /* pp_head vaut NULL, on sort */
          err = 1;
       }
     
     
       return err;
    }
     
    <snip, RAS>

  6. #6
    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 : 48
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Ok ok, merci mais une petite question pour satisfaire ma curiosité .... pourquoi diable tu met toujours un "ADD_NB" ou encore parfois "dummy" alors qu'ils ne seront surement jamais utilisés ? Moi j'ai toujours le strict minimum !

    Pour l'algo du retrait du dernier noeud, pour le moment c'est le seul moyen que j'ai trouvé je reflechi encore

    ....Quelques petites modifs ...
    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
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
     
    #include <stdio.h>
    #include <stdlib.h>
     
     
    typedef enum
    {
       ADD_AT_BEGIN,
       ADD_AT_END,
     
    } add_type_e;
     
    typedef enum
    {
       REMOVE_FIRST,
       REMOVE_LAST,
     
    } remove_type_e;
     
     
    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, add_type_e add_type)
    {
       int err = 0;
     
     
       if (pp_head != NULL)
       {
          /* Allocation en memoire du nouveau noeud. */
          struct node *p_new = malloc (sizeof *p_new);
     
          /* 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_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, remove_type_e remove_type)
    {
       int err = 0;
     
     
       if (pp_head != NULL)
       {
          switch (remove_type)
          {
             /* On supprime le premier noeud de la liste. */
             case REMOVE_FIRST :
             {
                struct node *p_node = *pp_head;
     
                p_node = p_node->p_next;
                free (*pp_head);
                *pp_head = p_node;
             }
             break;
     
             /* On supprime le dernier noeud de la liste. */
             case REMOVE_LAST :
             {
                if (*pp_head != NULL)
                {
                   /* 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_node2->p_next;
                   }
     
                   /* Supression du dernier noeud de la liste. */
                   p_node1->p_next = NULL;
                   free (p_node2);
                }
                else
                {
                   /* *pp_head vaut NULL, aucun noeud dans la liste. */
                   err = 1;
                }
             }
             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 :
    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 !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  7. #7
    Expert éminent
    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
    Par défaut
    Citation Envoyé par CSoldier
    pourquoi diable tu met toujours un "ADD_NB" ou encore parfois "dummy" alors qu'ils ne seront surement jamais utilisés ?
    J'ai rappelé qu'en C90 le dernier élément d'un enum ne devait pas être suivi d'une ','. Ca signifie que chaque fois qu'on ajoute u élément dans une liste d'enum, il faut gérer cette virgule. Etant un informaticien d'expérience (c'est à dire un flemmard patenté), j'ai pris l'habitude de placer un élément de fin de liste, certes plus ou moins utile fonctionellement, mais très utile sur le plan de la maintenance du code. Cet élement est par défaut 'dummy' quand il n'a pas de rôle particulier (ou xxx_dummy pour éviter les collisions). Mais souvent, on crée des constantes automatiques, c'est à dire numérotées de 0 à N. Dans ce cas, le dernier élément (N) est automatiquement le nombre d'éléments de la liste. Là, il devient utile (taille de tableau, limite de boucle, contrôle de paramètre...)

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef enum
    {
       OK,
       ERR_MEMORY,
       ERR_PARAMETER,
       ERR_NB
    };
    Ajouter un code d'erreur :
    Copié/collé de 3 secondes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    typedef enum
    {
       OK,
       ERR_MEMORY,
       ERR_PARAMETER,
       ERR_IO,
       ERR_NB
    };
    Pour l'algo du retrait du dernier noeud, pour le moment c'est le seul moyen que j'ai trouvé je reflechi encore
    Ce qu'il faut c'est ensuite créer un scénario de test qui passe par tous les cas et vérifier le comportement.

  8. #8
    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 : 48
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Ca te va ca ?
    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 !

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

    Noeud ajoute en debut de liste !
    Affichage de la liste :
    5
    10
    Fin de la liste !

    Noeud ajoute en fin de liste !
    Affichage de la liste :
    5
    10
    15
    Fin de la liste !

    Suppression de la liste :
    La liste a ete supprimee !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  9. #9
    Expert éminent
    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
    Par défaut
    Citation Envoyé par CSoldier
    Ca te va ca ?
    Encore une fois, c'est à toi que ça doit aller. C'est à toi de créer tes scénarios de validation, eux seuls te donneront la réponse. Je ne vais pas corriger tout ce que tu fais. Je t'ai donné les clés, les outils, tu as tout en main...

  10. #10
    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 : 48
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par CSoldier
    Ca te va ca ?
    Encore une fois, c'est à toi que ça doit aller. C'est à toi de créer tes scénarios de validation, eux seuls te donneront la réponse. Je ne vais pas corriger tout ce que tu fais. Je t'ai donné les clés, les outils, tu as tout en main...
    Mais moi ca me va, le resultat est celui que je voulais avoir va juste falloir que je test avec le retrait d'un noeud en milieu de liste c'est tout
    En tous cas, merci miiles fois pour tous tes conseils et corrections ... tu peut pas savoir à quel point j'ai aimé ton ptit cours (si c'est fini lol) !

    Je crois que maintenant je vais me pencher sur une liste double !

    PS : Je vais suivre les cours d'algo sur developpez ... car c'est tout de meme bien pratique !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Petite question sur les types.
    Par carlesup3 dans le forum Caml
    Réponses: 8
    Dernier message: 07/07/2012, 19h43
  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, 00h47
  3. petite question (type de retours covariants)
    Par Jabawock dans le forum C++
    Réponses: 6
    Dernier message: 21/08/2007, 08h06
  4. petite question sur les types de champs
    Par charlie koller dans le forum Débuter
    Réponses: 2
    Dernier message: 21/02/2007, 17h57
  5. question sur le type "void *"
    Par ChriGoLioNaDor dans le forum C++
    Réponses: 4
    Dernier message: 10/02/2006, 11h27

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