Partage
  • Partager sur Facebook
  • Partager sur Twitter

Modifier valeur dans une liste chainée

    27 septembre 2022 à 14:17:47

    Bonjour, j'ai une structure d'une liste chainée qui se présente comme ça 
    typedef struct elem{
        int valeur ;
        struct elem *suivant ;
    }element ;
    
    typedef element *liste ;
    
    

    J'ai une liste que je définis comme ça

    liste liste_1 ;

    Mais je n'arrive pas à modifier le paramètre valeur étant donné que ma "liste" est un pointeur

    int v=6 ;
    liste_1->valeur = 6 ; //ERREUR ICI

    Quelqu'un a une idée svp ?

    Merci !


    • Partager sur Facebook
    • Partager sur Twitter
      27 septembre 2022 à 14:52:38

      Ici, liste_1 n'est pas un pointeur. C'est la structure.
      Dans ce cas, on écrit:
      liste_1.valeur = 6;     // avec un point (.)
      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        27 septembre 2022 à 16:28:37

        Et si, liste_1 est un pointeur et il doit être initialisé avant de le déréférencer (avant de l'utiliser) !

        C'est à dire qu'il doit être initialisé avec l'adresse d'une zone mémoire valide (allouée).

        Dans ce cas on peut utiliser malloc pour allouer de la mémoire vers laquelle on le fera pointer.

        • Partager sur Facebook
        • Partager sur Twitter
        ...
          27 septembre 2022 à 17:03:47

          @rouIoude: J'ai manqué le '*' dans la définition ...
          typedef element *liste ;
          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            27 septembre 2022 à 17:59:27

            JnouniKhaliday a écrit:


            int v=6 ;
            liste_1->valeur = 6 ; //ERREUR ICI

            Quelqu'un a une idée svp ?

            Merci !


            Faudrait nous dire quel genre d'erreur

            • à la compilation : quel message, à propos de quelle ligne ?
            • à l'exécution : avec quel code ? qui est censé faire quoi ? et qui fait quoi ?
            • Partager sur Facebook
            • Partager sur Twitter
              28 septembre 2022 à 17:21:46

              En gros ma console plante et se ferme donc aucune erreur de compilation. Et quand j'essaye de remplacer "->" par "." j'ai le message d'erreur suivant :

              error : 'liste_1' is a pointer; did you mean to use '->' ?

              • Partager sur Facebook
              • Partager sur Twitter
                28 septembre 2022 à 17:50:21

                rouIoude a écrit:

                C'est à dire qu'il doit être initialisé avec l'adresse d'une zone mémoire valide (allouée).

                Dans ce cas on peut utiliser malloc pour allouer de la mémoire vers laquelle on le fera pointer.

                Tant que tu n'as pas initialisé le pointeur avec l'adresse d'un espace mémoire valide tu ne peux pas l'utiliser !

                Ton pointeur, il ne pointe nulle part et surtout n'importe où, donc plantage si tu l'utilises avant de l'avoir initialisé avec l'adresse d'un espace mémoire valide

                PS : Avec un pointeur c'est bien l'opérateur -> qu'il faut utiliser. 

                -
                Edité par rouIoude 28 septembre 2022 à 17:51:33

                • Partager sur Facebook
                • Partager sur Twitter
                ...
                  28 septembre 2022 à 17:53:02

                  > En gros ma console plante et se ferme donc aucune erreur de compilation

                  Si la console "plante", c'est à l'exécution, pas à la compilation (qui a pu produire des avertissements en trouvant le code chelou, il faudrait regarder).

                  Et ça veut dire quoi, que "la console plante" ?  Elle se referme illico ? Pourquoi elle ne devrait pas se refermer ?

                  On n'a pas assez de code sous les yeux pour pouvoir en dire quelque chose qui soit basé sur des faits plutôt que des suppositions. On va pas jouer aux devinettes sur des millions de causes possibles.


                  -
                  Edité par michelbillaud 28 septembre 2022 à 17:54:47

                  • Partager sur Facebook
                  • Partager sur Twitter
                    28 septembre 2022 à 18:00:31

                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <stdbool.h>
                    
                    typedef struct elem{
                        int valeur ;
                        struct elem *suivant ;
                    }element ;
                    
                    typedef element *liste ;
                    
                    bool is_empty(liste list1){
                        if (list1){
                            printf("La liste contient au moins un élément") ;
                            return false ;
                        }
                        else{
                            printf("La liste est vide.") ;
                            return true ;
                        }
                    }
                    
                    liste insert_head (liste list1, int v){
                        liste temp ;
                        temp =( element*)malloc(sizeof(element)) ;
                        temp->valeur=v ;
                        temp->suivant=list1->suivant ;
                        list1 = temp ;
                        return list1 ;
                    }
                    
                    liste insert_tail (liste list1, int v){
                        liste parcours, temp ;
                        parcours = ( element*)malloc(sizeof(element)) ;
                        temp = ( element*)malloc(sizeof(element)) ;
                        parcours = list1 ;
                        while (parcours->suivant){
                            parcours = parcours->suivant ;
                        }
                        temp =( element*)malloc(sizeof(element)) ;
                        temp->valeur=v ;
                        parcours->suivant = temp ;
                        return list1 ;
                    }
                    
                    liste remove_head (liste list1){
                        liste temp, temp2 ;
                        temp = ( element*)malloc(sizeof(element)) ;
                        temp2 = ( element*)malloc(sizeof(element)) ;
                        temp = list1->suivant ;
                        temp2 = temp->suivant ;
                        list1 = temp2 ;
                        free(temp) ;
                        return list1 ;
                    }
                    
                    liste remove_tail (liste list1){
                        liste parcours1, parcours2 ;
                        parcours1 = ( element*)malloc(sizeof(element)) ;
                        parcours2 = ( element*)malloc(sizeof(element)) ;
                        parcours1 = list1 ;
                        parcours2 = parcours1 ;
                        while (parcours2->suivant){
                            parcours1 = parcours2 ;
                            parcours2 = parcours2 -> suivant ;
                        }
                        free(parcours2) ;
                        free(parcours1->suivant) ;
                        return list1 ;
                    }
                    
                    void print_list(liste list1){
                        liste parcours ;
                        parcours = ( element*)malloc(sizeof(element)) ;
                        parcours = list1->suivant ;
                        printf("\n[") ;
                        while (parcours->suivant){
                            printf("%d, ",parcours->valeur) ;
                            parcours = parcours->suivant ;
                        }
                        printf("%d]",parcours->valeur) ;
                    }
                    
                    
                    int gestion_liste(liste list1, int c){
                        int reponse ;
                        if (c==0){
                            printf("Entrez le chiffre a ajouter en queue\n") ;
                            scanf("%d",&reponse) ;
                            insert_tail(list1, reponse) ;
                        }
                        else if (c==1){
                            printf("Entrez le chiffre a ajouter en tete\n") ;
                            scanf("%d",&reponse) ;
                            insert_head(list1, reponse) ;
                        }
                        else if (c==2){
                            printf("Suppression de la queue de la liste\n") ;
                            remove_tail(list1) ;
                        }
                        else if (c==3){
                            printf("Suppression de la tete de la liste\n") ;
                            remove_head(list1) ;
                        }
                        else if (c==4){
                            print_list(list1) ;
                        }
                        else{
                            return false ;
                        }
                        return true ;
                    }
                    
                    int main()
                    {
                        bool continuer = true ;
                        int rep ;
                        liste liste_1 ;
                        liste_1 = ( element*)malloc(sizeof(element)) ;
                        while (continuer){
                            printf("Que voulez-vous faire ?\n") ;
                            printf("0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste\n") ;
                            scanf("%d",&rep) ;
                            continuer = gestion_liste(liste_1,rep) ;
                        }
                    
                    }
                    

                    Voilà le code complet. Quand par exemple j'entre "0" (pour ajouter un élément) et qu'après je rentre "5" (élément à ajouter en queue de la liste), la console tourne dans le vide alors qu'elle devrait me redemander "Que voulez-vous faire ?".
                    • Partager sur Facebook
                    • Partager sur Twitter
                      28 septembre 2022 à 18:21:09

                      Le moins qu'on puisse dire est que tu aimes faire des malloc ...
                          parcours = ( element*)malloc(sizeof(element)) ;
                          temp = ( element*)malloc(sizeof(element)) ;
                          parcours = list1 ;
                      Et temp->suivant tu ne l'initialises pas à la fin?
                      Pourquoi retourner list1 si tu ne le modifie pas? (tu modifies ses composantes, mais c'est un pointeur)

                      OK on est obligé de le retourner si on n'a pas de descripteur de liste ...
                      C'est plus compliqué sans descripteur de liste. Comment peut-on avoir une liste vide?

                      Est-ce que tu le gères?

                      Dans le main, tu n'initialises pas liste_1. Ça vaut n'importe quoi.

                      Ton insertion au début ne marchera pas. Le suivant de NULL c'est n'importe où (dans la nature ...)

                      -
                      Edité par PierrotLeFou 28 septembre 2022 à 18:55:46

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                        28 septembre 2022 à 18:55:38

                        Effectivement, il bien trop de malloc et pas les free qui vont avec ! 

                        A mon avis, il faut tout reprendre du début. Et avant de faire l'interface, il faut faire les principales fonctions et les tester !

                        Tu peux commencer par la fonction insert_head par exemple et la fonction print_list pour voir si ta liste se rempli bien. Tu t'occuperas du reste quand cela fonctionnera !

                        Ne pas oublier que les paramètres de fonctions sont passé par copie.

                        On ne transtype (cast) pas le retour de malloc.

                        • Partager sur Facebook
                        • Partager sur Twitter
                        ...
                          28 septembre 2022 à 19:07:03

                          Si tu veux suivre cette idée, regardes au moins ce lien  ...

                          http://sdz.tdct.org/sdz/les-listes-chainees-2.html

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Le Tout est souvent plus grand que la somme de ses parties.

                            29 septembre 2022 à 11:46:38

                            Je vais suivre vos conseils mais du coup les malloc je les ai ajouté parce que on m'a dit de le faire un peu plus haut, et là personne ne donne de réponse à mon problème, à savoir pourquoi est ce que je ne peux pas accéder aux valeurs de mes noeuds en utilisant "list1->valeur", c'est ça dont j'ai besoin.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              29 septembre 2022 à 12:00:17

                              JnouniKhaliday a écrit:

                              Voilà le code complet. Quand par exemple j'entre "0" (pour ajouter un élément) et qu'après je rentre "5" (élément à ajouter en queue de la liste), la console tourne dans le vide alors qu'elle devrait me redemander "Que voulez-vous faire ?".


                              Ce n'est pas le cas ici

                              $ gcc -Wall -Wextra a.c
                              $ ./a.out 
                              Que voulez-vous faire ?
                              0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste
                              0
                              Entrez le chiffre a ajouter en queue
                              5
                              Que voulez-vous faire ?
                              0 = Ajouter queue ; 1 = Ajouter tete ; 2 = Supprimer queue ; 3 = Supprimer tete ; 4 = Afficher liste
                              


                              Histoire de dire quelque chose :

                              A partir de ce bout de code

                              typedef element *liste ;
                               
                               
                              liste insert_head (liste list1, int v){
                                  liste temp ;
                                  temp =( element*)malloc(sizeof(element)) ;
                                  temp->valeur=v ;
                                  temp->suivant=list1->suivant ; 
                               

                              1. Définir un typedef pour des pointeurs est généralement une mauvaise idée.

                              • En C, on est quasiment obligé tout le temps de savoir si un truc contient des données ou est l'adresse d'une donnée, on n'en fera pas la même chose. . La preuve dans ton malloc, tu parles d'element. Ou sinon tu parlerais de *temp, ce qui implique de savoir que c'est un pointeur. C n'est pas le langage idéal pour l'abstraction
                              • ca fait un nom de plus à garder en tete, alors que element* fait l'affaire

                              2. Si tu veux faire de l'abstraction, définis plutot list comme une structure contenant un pointeur vers son premier élément. Tu nous remerciera quand tu passeras à des listes doublement chainées et/ou indication du nombre d'éléments.

                              3. Depuis des temps où vous étiez pas nés (comme les poissons), malloc retourne un pointeur génériques (void *) que le langage C convertit comme un grand.  Il faut donc eliminer les typecasts explicites qui n'apportent aucune information, et donc causent du bruit.

                              4. il est de bon goût de combiner déclaration et initialisation des variables à une valeur qui a un sens, quand c'est possible.

                              Donc ça donnerait

                              liste insert_head (element *first, int v){
                                  element *temp = malloc(sizeof(element)) ;
                                  ;...
                              

                              ce qui est quant même plus simple, et plus lisible

                              5. Il faut éviter de se répéter, allouer un élément et initialiser ses champs est une opération fréquente,  qu'on condense dans une fonction

                              element * nouvel_element(int valeur, element *suivant) 
                              {
                                  element *nouveau = malloc(element);
                                  nouveau->valeur = valeur;
                                  nouveau->suivant = suivant;
                                  return nouveau;
                              }
                              

                              et qu'on réutlilise à tour de bras

                              liste insert_head (element *first, int v)
                              {
                                  element *temp = nouvel_element(v, ....);
                              


                              PS: les listes avec élément fictif au début, c'est pas une idée géniale. Ca traine dans quelques bouquins célèbres, mais à la rubrique "y en a aussi qui font comme ça" (*).  En fait l'élément fictif tient lieu, maladroitement, de la structure avec pointeur sur le premier vrai élément, voir plus haut.

                              (*) on faisait effectivement parfois comme ça en assembleur, il y a des décennies. Autres langages, autres considérations de génie logiciel (on ne définissait pas de _types_, en assembleur)

                              -
                              Edité par michelbillaud 29 septembre 2022 à 13:45:39

                              • Partager sur Facebook
                              • Partager sur Twitter
                                29 septembre 2022 à 17:18:22

                                Ok merci beaucoup pour ta réponse j'en prends bonne note, t'as l'air d'avoir raison et c'est vrai que ma structure est un peu bizarre mais je me base sur des cours et instructions de mon prof (pour le malloc, ou le typedef element *liste), du coup je sais pas vraiment quoi faire...

                                Je vais essayer de chopper la correction et de la comparer avec mon prog et les conseils que tu m'as donné, mais je te suis vraiment reconnaissant !!!

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  29 septembre 2022 à 18:27:57

                                  > t'as l'air d'avoir raison

                                  Force est de constater que j'ai TOUJOURS raison.

                                  > mais je me base sur des cours et instructions de mon prof

                                  Il faut toujours faire comme dit le prof, pour les trucs qu'il dit de faire (et de lui rendre pour qu'il les note).

                                  Après, rien n'empêche de regarder plusieurs façons, et de comparer. Et de chercher à comprendre pourquoi les uns font comme ci et les autres comme ça. Ils ont certainement des raisons. Pour certains, c'est juste qu'ils l'ont vu quelque part dans un bouquin où ils piquent les exos (Sedgewick ?) sans se poser de questions.

                                  -
                                  Edité par michelbillaud 29 septembre 2022 à 18:33:18

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    29 septembre 2022 à 19:10:06

                                    > Force est de constater que j'ai TOUJOURS raison.
                                    Il est comme moi. Il a toujours raison, sauf quand il a tort. :)
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Le Tout est souvent plus grand que la somme de ses parties.

                                    Modifier valeur dans une liste chainée

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown