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 :

Parcourir et afficher les elements d'une liste chainee


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut Parcourir et afficher les elements d'une liste chainee
    Bonsoir,

    j'ai fait un petit programme permettant de stocker les arguments qu'on entre dans une liste chainee, ca fontionne plutot bien, mais je veux faire une deuxieme fonction qui la parcourt en affichant chaque maillon, et la je plante... Ce qui est normal, mais je ne vois pas comment faire autrement (on m'a dit au'il etait plus simple de l'afficher a l'envers mais ca ne m'a pas beaucoup aide), voici le code:

    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
    void            my_print_list(t_list **params)
    {
      t_list        *moove;
    
      moove = *params;
      while (moove != 0)
        {
          putstr(moove->arg);  SEGMENTATION FAULT 
          moove = moove->next;
        }
    }
    
    void            my_params_in_list(t_list **params, char **av)
    {
      int           y;
      int           x;
      t_list        *new;
      t_list        *moove;
    
      y = 0;
      while (av[y])
        {
          new = malloc(sizeof(*new));
          new->arg = malloc((my_strlen(av[y]) + 1) * (sizeof(new->arg)));
          new->next = 0;
          x = 0;
          while (av[y][x])
            {
              new->arg[x] = av[y][x];
              x++;
            }
          if (*params == 0)
            *params = new;
          else if (*params != 0)
            {
              moove = *params;
              while (moove->next != 0)
                moove = moove->next;
              moove->next = new;
            }
          y++;
        }
    }
    
    int     main(int ac, char **av)
    {
      t_list        *params;
    
      params = malloc(sizeof(*params));
      my_params_in_list(&params, av);
      my_print_list(&params);
    }
    Merci de me donner un petit coup de main ! Bonne soiree.

  2. #2
    Membre éclairé
    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
    Points : 842
    Points
    842
    Par défaut


    On utilise généralement (toujours ?) NULL pour vérifier si un pointeur est nul et pas 0

    Dans cette ligne là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new->arg = malloc((my_strlen(av[y]) + 1) * (sizeof(new->arg)));
    sizeof(new->arg) vaudra la taille d'un pointeur mais comme toi tu ne veux que la taille d'un char (pour la chaîne de caractère) ça ne va pas

    Au lieux de faire une boucle tu peux utiliser 'strcpy' :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            while (av[y][x])
            {
              new->arg[x] = av[y][x];
              x++;
            }
    Ton segfault doit venir de la boucle décrite juste au dessus. Tu copies toute la chaîne mais tu ne mets pas le '\0' de fin de chaîne (pourtant tu l'as alloué !).

    Dans ta fonction my_print_list tu n'as pas besoin de passer l'adresse de ta liste car tu ne modifies pas sa valeur.

    @+

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Pour les listes chainees on m'a dit d'utiliser 0 et non NULL...


    Ok ! j'avais bien vue que mon malloc était trop grand mais je comprenais pas pourquoi... Donc si je fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new->arg = malloc((my_strlen(av[y]) + 1) * (sizeof(*arg)));
    Ca me ferra bien un malloc de type char* ?


    Pour le '\0', quel boulet.... C'est le genre d'erreur d'inattention que je détecte pas avant d'avoir lâcher un peu mon code, merci pour le gain de temps !

    Quelques secondes plus tard...

    Je segfault toujours au meme endroit, pourtant j'utilise strcpy et je suppose qu'il copie egalement le '\0' de la chaine.

    Au cas ou, voici le nouveau code:

    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
     
    void            my_print_list(t_list *params)
    {
      t_list        *moove;
     
      moove = params;
      while (moove != 0)
        {
          my_putstr(moove->arg);
          moove = moove->next;
        }
    }
     
     
    void            my_params_in_list(t_list **params, char **av)
    {
      int           y;
      t_list        *new;
      t_list        *moove;
     
      y = 0;
      while (av[y])
        {
          new = malloc(sizeof(*new));
          new->arg = malloc((my_strlen(av[y]) + 1) * (sizeof(new->arg)));
          new->next = 0;
          strcpy(new->arg, av[y]);
          if (*params == 0)
            *params = new;
          else if (*params != 0)
            {
              moove = *params;
              while (moove->next != 0)
                moove = moove->next;
              moove->next = new;
            }
          y++;
          my_putstr(new->arg); /*ici ca me print les arguments comme il faut*/
          my_putstr("\n");
        }
    }
     
    int     main(int ac, char **av)
    {
      t_list        *params;
     
      params = malloc(sizeof(*params));
      my_params_in_list(&params, av);
      my_print_list(params);
    }

  4. #4
    Membre éclairé
    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
    Points : 842
    Points
    842
    Par défaut
    Tu peux faire comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new->arg = malloc((my_strlen(av[y]) + 1) * (sizeof(*new->arg)));
    Essaye ce code et dis moi si ça segfault encore :

    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
    void            my_print_list(t_list *params)
    {
    	t_list        *moove;
     
    	moove = params;
    	while (moove != NULL)
        {
    		puts(moove->arg);
    		moove = moove->next;
        }
    }
     
    void            my_params_in_list(t_list **params, char **av)
    {
    	int           y;
    	t_list        *new;
    	t_list        *moove;
     
    	y = 0;
    	while (av[y] != NULL)
        {
    		new = malloc(sizeof(*new));
    		new->arg = malloc((strlen(av[y]) + 1) * (sizeof(*new->arg)));
    		new->next = NULL;
     
    		strcpy(new->arg, av[y]);
     
    		if (*params == NULL)
    			*params = new;
    		else
            {
    			moove = *params;
    			while (moove->next != NULL)
    				moove = moove->next;
    			moove->next = new;
            }
    		y++;
        }
    }
     
    int     main(int ac, char **av)
    {
    	t_list        *params = NULL;
     
    	my_params_in_list(&params, av);
    	my_print_list(params);
     
    	return EXIT_SUCCESS;
    }

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Ca fonctionne... Je reve ou tu as simplement mit "NULL" partout a la place de mes 0 ??^^

    Je vois que tu as initialiser le pointeur sur structure dans le main, je pense que mon segmentationfault venait d'ici, enfin j'espère, car si c'est a cause des 0 je serai traumatise.

    En tout cas merci beaucoup pour l'efficacité des aides que j'ai reçut !

    Bonne soirée a tous !

    (Je viens de tester en remplaçant tous les NULL par des 0 et ca fonctionne aussi même si c'est vrai que des pointeurs pointes sur NULL et non 0 en théorie...)

  6. #6
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    L'erreur était effectivement à cause de la non initialisation du pointeur sur structure dans le main.

    NULL peut être défini comme 0 ou comme (void*) 0, mais il est préférable de mettre NULL plutôt que 0 pour des pointeurs pour une question de clarté du code (on voit immédiatement que la grandeur est un pointeur et non une grandeur numérique)

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    J'ai une derniere question avant de clore ce sujet !

    J'ai voulut voir si j'etais capable de supprimer les maillons qui contiendraient un mot precis (VIRUS) dans l'exemple suivant), ca fonctionne tres bien sauf qu'en relisant mon code je me suis appercut que j'ai fait une erreur d'inattention, et lorsque je la corrige, ca ne fonctionne plus^^ (encore plus frustrant qu'une veritable erreur^^)

    J'ai l'impression que mon code devrait "sauter" un maillon en trop, je detail ca sur le code (si les commentaires ne vous semblent pas logique faites le moi savoir et je vous expliquerait pourquoi je l'imagine comme ca):

    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
    void            my_print_list(t_list **params)
    {
      t_list        *moove;
      t_list        *epur;
     
      moove = *params;
      if (strcmp(moove->arg, "VIRUS") == 0)
        {
          while ((moove->arg, "VIRUS") == 0)
            moove = moove->next;
          epur = moove->next; /*Ici je serais plutot tente de dire, epur = moove*/
        }
      else
        epur = *params;
      moove = moove->next; /* moove est un maillon devant epur */
      while (moove != 0)
        {
          if (strcmp(moove->arg, "VIRUS") == 0)
            {
              while ((moove->arg, "VIRUS") == 0)
                moove = moove->next; /* En sortant de cette boucle, moove devrait etre sur le prochain maillon de epur*/
              epur->next = moove->next; /* ici il me semblerait donc plus logique de dire epur->next = moove, mais ca ne fonctionne plus */
              moove = moove->next;
            }
          if (strcmp(moove->arg, "VIRUS") != 0)
            {
              moove = moove->next;
              epur = epur->next;
            }
          puts(epur->arg);
        }
    }

  8. #8
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Je ne comprend pas reellement ton code.

    Il n'y a aucune notions de suppression réelle de cellule.
    J'ai plutot l'impressions que tu affiche toute les chaine differente de "VIRUS" sans tenter de retirer ce maillon de la chaine.


    Si tu veux supprimer le maillon, il faut regarder plusieurs cas (tu utilise apparement une liste simplement chainé non circulaire) :

    Le cas ou la suppression est au debut
    Le cas ou la suppression est en milieu
    Le cas ou la suppression est a la fin

    Apparement, tu autorise le fait qu'il y ait des doublons a n'importe quelle endroit.

    Dis nous en plus sur ce que tu appele supprimer, car si tu ne veux qu'afficher les cellule contenant un mot different sans supprimer ledit maillon de la chaine, une boucle while + une condition feront l'affaire.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Je veux en effet supprimer les maillons contenants "VIRUS", si je ne fait que de l'affichage comment je pourrais vraiment supprimer ces maillons ?

  10. #10
    Membre éclairé
    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
    Points : 842
    Points
    842
    Par défaut
    Ta fonction my_print_list est, comme son nom l'indique, faite pour l'affichage.
    Il faut que tu fasses une fonction supprimerMot par exemple qui prenne en paramètre le mot que tu souhaite enlever de ta liste chaînée.

    L'idée c'est d'avoir un pointeur sur le maillon précédent et de comparer le maillon présent. Si le maillon présent contient le mot tu récupère le pointeur suivant et tu libères ta mémoire (important!).
    Ensuite tu fais pointer ton maillon précédent sur le pointeur sauvegardé (suivant).

    Normalement tu n'as rien à toucher dans ta fonction my_print_list ! C'est juste une fonction d'affichage rien d'autre

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Si ma fonctIon s'appelle comme ca c'est parceque je faisais de l'affichage mais j'ai recode autre chose dedans, il me semble que c'est bien ce que je fais, ici mon t_list *moove est toujours un maillon devant mon t_list *epur et si moove->arg == 'VIRUS" je fais une boucle moove = moove->next et ensuite je dis epur->next = moove->next (je ne comprends pas d'ailleurs pourquoi je ne devrais pas faire epu->next = moove) enfin je pense que le code est plus explicite que ce poste, mais en gros moove parcourt la chaine et epur recupere que les maillons qui n'ont pas "VIRUS" dans leur char *arg.

  12. #12
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 078
    Points : 2 338
    Points
    2 338
    Par défaut
    Tes maillon sont certainement alloué via malloc, donc si tu veux les supprimer, il faut utiliser free(), sinon je vois mal comment tu compte faire.

    Pour une liste simplement chainé non circulaire (ce que tu n'as toujours pas confirmer), pouet_forever te donne presque toutes la marche a suivre :

    Si le mot est en debut de chaine : tu fais pointer un pointeur sur la cellule que tu va supprimer. Puis, tu modifie le pointeur de tete afin qu'il pointe le maillon suivant. free sur le pointeur qui pointe la cellule a supprimer.

    Pour le reste, relis le post de pouet_forever.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Mon but est de faire une liste simplement chainee non circulaire, puis de supprimer les maillons contenants le mot "VIRUS", j'ai oublie de repondre a un post qui me le demande un peu plus haut.

    Je viens de recoder ma fonction, ca fontionne mais j'aimerais savoir si cette fois je supprime bien les maillons en m'y prenant de cette maniere:

    (Pour plus de lisibilite je poste uniquement la fonction concernee, je rappel donc que t_list *params est ma chaine, dont chaque maillon comporte un mot dans une variable char *arg).

    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
    void            delete_one_maillon(t_list **params)
    {
      t_list        *moove;
      t_list        *epur;
    
      /* verif_begin();*/
      epur = *params;
      moove = epur->next;
      while (moove != NULL)
        {
          if (strcmp(moove->arg, "VIRUS") == 0)
            {
              while (strcmp(moove->arg, "VIRUS") == 0)
                {
                  free(moove);
                  moove = moove->next;
                }
              epur->next = moove;
              epur = epur->next;
              moove = moove->next;
              puts(epur->arg);
            }
          else if (strcmp(moove->arg, "VIRUS") != 0)
            {
              epur = epur->next;
              moove = moove->next;
              puts(epur->arg);
            }
          /* verif_end(); */
        }
    }

  14. #14
    Membre éclairé
    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
    Points : 842
    Points
    842
    Par défaut
    Ton code est incorrect.
    Si tu as le mot "VIRUS" en premier maillon tu ne le supprimeras pas.

    Cette ligne est incorrecte, tu libères ta mémoire et ensuite tu essayes d'accéder à l'élément suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    free(moove);
    moove = moove->next;
    Il faudrait faire l'inverse.

    Il n'est pas utile de remettre un 'else if', un seul if suffit parce que tu as déjà testé avec ton if que "VIRUS" n'était pas là.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 77
    Points : 50
    Points
    50
    Par défaut
    Je ne comprends pas pourquoi, si j'avance d'un maillon avant de free admettons que j'ai:

    "il" "y" "a" "un" "VIRUS" "VIRUS" "VIRUS"

    je garderai:

    "il" "y" "a" "un" "VIRUS"

    non ?

  16. #16
    Membre éclairé
    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
    Points : 842
    Points
    842
    Par défaut
    Personnellement ta boucle while je l'aurais enlevée et tu n'aurais pas ce 'souci'.
    Après si tu veux la garder il te faut créer une variable intermédiaire pour sauvegarder ton pointeur, libérer ta mémoire et le réaffecter.

    Sachant que tu veux supprimer tous tes maillons où VIRUS est présent tu n'as pas de raison de garder le dernier

    Tu auras : il y a un

Discussions similaires

  1. [Débutant] Afficher les elements d'une liste
    Par mlio91 dans le forum Développement Sharepoint
    Réponses: 6
    Dernier message: 21/02/2014, 16h51
  2. afficher les element d'une file
    Par jalilc dans le forum C
    Réponses: 16
    Dernier message: 23/05/2006, 18h15
  3. Rechercher les element d'une liste dans une autre liste
    Par fessebleu dans le forum Langage
    Réponses: 30
    Dernier message: 24/04/2006, 21h23
  4. afficher les contenu d'une liste dynamiquement
    Par mzt.insat dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 06/04/2006, 18h02
  5. Réponses: 29
    Dernier message: 03/11/2005, 10h37

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