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 :

Erreur liste chainée


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut Erreur liste chainée
    Bonjour,

    j'ai un long tme sur les listes chainées 'que j'ai l'impression d'avoir bine compris) cependant lors de l'exécution de mes deux fonctions de base je beug deja. Voici mon 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
    typedef struct cellule_t cellule_t;
    struct cellule_t{
    	int donnee;
    	cellule_t *suivant;
    };
     
    cellule_t *creercellule(int donnee){
    	cellule_t *liste=malloc(sizeof(cellule_t));
    	liste->donnee=donnee;
    	liste->suivant=NULL;
    	return liste;
    }
     
     
    void affiche_liste(cellule_t *liste){
    	cellule_t *tmp = NULL;
    	tmp=liste;
    	while (tmp){
    		printf("%d\t",tmp->donnee);
    	 	tmp=tmp->suivant;
    	}
    	printf("\n");
    }
     
    cellule_t *test_liste(){
    	int i=0;
    	cellule_t *liste = malloc(sizeof(cellule_t));
    	cellule_t *tmp = NULL;
    	tmp=liste;
    	for(;i<5;i++){
    		tmp=creercellule(i);
                    (((printf("%d\t",tmp->donnee);)))) pour bien vérifier que les donnee sont créer
    		tmp=tmp->suivant;
    	}
    	return liste;
    }
     
    int main(){
    	cellule_t *liste=test_liste();
    	affiche_liste(liste);
    	return 0;
    }
    Lors de l'exécution ma machine me renvoie seulement 0 ou 0 1 2 3 4 0 quand je met le printf. Je sais que je realloue de la mémoire avec ma fonction creercellule alors que le tmp en a deja une avec la tmp=liste mais je ne pense pas que cela dérange l'exécution. Ca fait bien 2h que je bloque sur ca alors que le reste de mes fonctions bien plus compliqués fonctionnent.
    Merci de vos réponses.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 123
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 123
    Points : 33 023
    Points
    33 023
    Billets dans le blog
    4
    Par défaut
    T'as essayé de dérouler ton algo à la main ? Ça prend 2mn et te montre assez efficacement le problème...

    cellule_t *liste = malloc(sizeof(cellule_t)); crée une nouvelle cellule, un maillon de la chaîne
    cellule_t *tmp = liste; crée une deuxième variable pointant vers le contenu de liste. Ok pourquoi pas..
    for(;i<5;i++){ effectuera une action 5 fois
    tmp=creercellule(i); chaque action crée une cellule par laquelle tu accèdes via tmp
    tmp=tmp->suivant; } puis tmp pointe vers NULL
    return liste; puis on retourne le maillon initial

    Et ? À quel moment le lien entre les maillons est fait ?
    Où se trouve la libération de toute cette mémoire allouée ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Je pense que le lien entre les chainons ce fait lorsque le pointeur tmp qui pointe vers NULL se voit justement réallouer de la mémoire par créer_cellule. On a donc en gros :
    -tmp et liste qui pointe vers la premiere cellule
    -tmp pointe vers une premiere cellule de donnee i grace a creer_cellule. (on lui allouer de la mémoire (une cellule) grace a malloc)
    -puis tmp=tmp->suivant qui pointe vers NULL
    -(la boucle reccomence) tmp pointe vers une deuxieme cellule de donnee i grace a creer_cellule
    etc...
    Et pour moi la mémoire alloué par les malloc reste dans le tas et ceci représente justement la liste chainée, et on accès au premier élement de cette liste avec le pointeur liste car on a ''travailler'' avec tmp et non liste donc liste pointe toujours vers la premiere cellule de ma liste. on peut ensuite parcourir la liste avec liste=liste->suivant qui pour moi parcourt la liste creer par ma fonction.

    Cependant je savais que le probleme étant en effet le lien antre les maillons car ma fonction affiche_cellule n'affiche que la premiere donnee 0. Mais cependant je ne comprend toujours pas pourquoi le lien entre mes maillons n'est pas effectué.

    Je viens de commencer C il a surement des énormes fautes, mais c'est comme ca que je vois mon code, et pour avancer dans quelque chose j'ai besoin de le comprendre parfaitement.

    Merci beaucoup pour ta réponse en tt cas, en esperant mieux comprendre la seconde fois.

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 571
    Points : 7 684
    Points
    7 684
    Par défaut
    Bonjour,

    Pour que le lien entre les maillons soit effectué, il faut forcément l'écrire quelque part. Aucune ligne de ton code n'effectue ce lien.
    Un pointeur, c'est une mémoire qui contient l'adresse d'une autre mémoire. Le pointeur qui est dans tes maillons doit donc à un moment être rempli avec l'adresse du maillon suivant.
    Par exemple, ligne 33 tu écris tmp=tmp->suivant;. Juste avant tmp contient l'adresse du maillon qui vient d'être créé. Donc le code lit la valeur de tmp->suivant qui à cet instant ne peut être que NULL, d'où ceci revient à écrire tmp=NULL;. On vient de modifier la valeur d'une variable locale, la ligne ne sert donc à rien!
    Je ne connais que trois manières de comprendre comment gérer un chaînage:
    - faire un dessin
    - faire un dessin
    - ou bien faire un dessin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     avant, on a un maillon :
    +---------+------+
    | valeur1 | NULL |
    +---------+------+
     après, on a deux maillons chaînés
    +---------+------+      +---------+------+
    | valeur2 |   --------->| valeur1 | NULL |
    +---------+------+      +---------+------+
                 ^
                 |Il a fallu écrire dans cette case, l'adresse du maillon suivant
    Chaque itération de ta boucle doit produire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
          +------+      +---------+------+
    liste:|   --------->| valeur1 | NULL |   A la fin de la première itération on a ça
          +------+      +---------+------+
     
          +------+      +---------+------+      +---------+------+
    liste:|   --------->| valeur2 |   --------->| valeur1 | NULL |   A la seconde, on a ça
          +------+      +---------+------+      +---------+------+
     
          +------+      +---------+------+      +---------+------+      +---------+------+
    liste:|   --------->| valeur3 |   --------->| valeur2 |   --------->| valeur1 | NULL |
          +------+      +---------+------+      +---------+------+      +---------+------+
    Et avant d'entrer dans la boucle on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          +------+
    liste:| NULL |        Donc avant la boucle, il n'y pas eu d'allocation!
          +------+

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 708
    Points : 31 018
    Points
    31 018
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Loannvrk Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(;i<5;i++){
    	tmp=creercellule(i);
    	(((printf("%d\t",tmp->donnee);)))) pour bien vérifier que les donnee sont créer
    	tmp=tmp->suivant;
    }
    j'ai un long tme sur les listes chainées 'que j'ai l'impression d'avoir bine compris)
    En tout cas, t'as bien compris que les parenthèses servaient à grouper certaines opérations. Tout comme Gauvain qui double ses 360° pour doubler les procédures de sécurité, t'as triplé tes parenthèses. Ainsi vraiment aucun risque que printf() soit combiné avec autre chose (d'autant plus qu'il n'y a rien d'autre...). Sauf que t'en as fermé une de plus (probablement aussi pour plus de sécurité je présume...)
    Sinon, mis à part la compréhension des listes chainées, as-tu bien compris aussi le rôle de l'opérateur "égal" (opérateur d'affectation !!!) ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Merci pour vos réponses, c'est vrai que j'ai pas été très vif sur ce probleme...
    J'ai donc vite refait ma fonction qui marche. Je vous laisse juger si vous pensez que j'ai compris mes erreurs ou j'ai juste eu de la chance.

    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
    cellule_t *creercellule(int donnee){
    	cellule_t *liste=malloc(sizeof(cellule_t));
    	liste->donnee=donnee;
    	liste->suivant=NULL;
    	return liste;
    }
     
     
    void affiche_liste(cellule_t *liste){
    	cellule_t *tmp = liste;
    	while (tmp){
    		printf("%d - >\t",tmp->donnee);
    	 	tmp=tmp->suivant;
    	}
    	printf("NULL\n");
    }
     
    cellule_t *test_liste(){
    	int i=0;
    	cellule_t *tmp = creercellule(i);
    	cellule_t *liste = tmp;
    	for(i=1;i<5;i++){
    		tmp->suivant=creercellule(i);
    		tmp=tmp->suivant;
    	}
    	return liste;
    }
    int main(){
    	cellule_t *liste=test_liste();
    	affiche_liste(liste);
    	return 0;
    }
    Ca m'affiche 0 - > 1 - > 2 - > 3 - > 4 - > NULL

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Meme avec un dessin je ne comprend pas la segfault que je me prends dans ce 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
    cellule_t *maximum(cellule_t *liste){
    	cellule_t *tmp = liste;
    	cellule_t *tmp2 = liste;
    	cellule_t *tmp3 = NULL;
    	while (tmp2){
    		tmp2 = tmp2->suivant;
    		if (tmp->donnee > tmp2->donnee){
    			tmp3=tmp;
    		}
    		else {
    			tmp3=tmp2;
    		}
    		tmp = tmp->suivant;
    		tmp2 = tmp->suivant;
    	}
    	return tmp3;
    }
    desolé mais j'ai encore du mal avec les listes j'ai limpression.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 708
    Points : 31 018
    Points
    31 018
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Loannvrk Voir le message
    J'ai donc vite refait ma fonction qui marche. Je vous laisse juger si vous pensez que j'ai compris mes erreurs ou j'ai juste eu de la chance.
    Ben mis à part que dans affiche_liste() tu peux remplacer ton while() par un for() (ok c'est du détail mais si on peut faire aussi bien tout en écrivant moins tout en restant lisible c'est toujours mieux), ton truc est correct. Ta fonction test_liste() est un peu confuse en première lecture (pourquoi créer le suivant ?) mais quand on la regarde mieux, on comprend sa logique qui est correcte. Tu peux quand-même l'améliorer en lui mettant le nombre de cellules à créer en paramètre.

    Toutefois, quand on manipule une liste, c'est toujours utile de créer une structure dédiée à la liste elle-même. Tu verras qu'ensuite ça t'aide à gérer plus facilement certains cas (comme par exemple quand on doit changer le premier élément).

    Citation Envoyé par Loannvrk Voir le message
    Meme avec un dessin je ne comprend pas la segfault que je me prends dans ce 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
    cellule_t *maximum(cellule_t *liste){
    	cellule_t *tmp = liste;
    	cellule_t *tmp2 = liste;
    	cellule_t *tmp3 = NULL;
    	while (tmp2){
    		tmp2 = tmp2->suivant;
    		if (tmp->donnee > tmp2->donnee){
    			tmp3=tmp;
    		}
    		else {
    			tmp3=tmp2;
    		}
    		tmp = tmp->suivant;
    		tmp2 = tmp->suivant;
    	}
    	return tmp3;
    }
    Tu vérifies que tmp2 existe, ok. Ensuite tu te positionnes sur son suivant et là, sans vérification, tu traites ce suivant Es-tu certain que ce suivant existe ???

    Citation Envoyé par Loannvrk Voir le message
    desolé mais j'ai encore du mal avec les listes j'ai limpression.
    Ici un exemple complet de liste chainée.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Merci pour ta réponse, je commence à m'y faire.

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    etudiant
    Inscrit en
    Mars 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : etudiant

    Informations forums :
    Inscription : Mars 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Sinon as tu un moyen qui me permettrait d'avoir une meuilleur compréhension algorithmique? J'entends par la comment la machine fonctionne, comment elle "réflechit", les méthodes mises en place pour qu'elle fonctionne, etc.. Je pense que ma comprehension en info passe beaucoup par ca.

    merci

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 708
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 708
    Points : 31 018
    Points
    31 018
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Loannvrk Voir le message
    Sinon as tu un moyen qui me permettrait d'avoir une meuilleur compréhension algorithmique? J'entends par la comment la machine fonctionne, comment elle "réflechit", les méthodes mises en place pour qu'elle fonctionne, etc.. Je pense que ma comprehension en info passe beaucoup par ca.
    Ben justement, ce qu'il faut que tu comprennes, c'est que la machine ne réfléchit pas. Elle se contente d'exécuter bêtement les opérations que tu lui donnes à faire. C'est donc à toi, qui ne dispose que d'opérations basiques (calculs, mémorisation de valeurs) de les organiser pour arriver au résultat.
    Quand tu auras compris ça tu seras à 80% du but. Tu gagneras encore 15% quand tu pourras dérouler ton code "à la main", c'est à dire prendre un papier et y modéliser tes variables et leurs valeurs au fur et à mesure que tu lis ton code (tu aurais fait ça, tu aurais vu de suite le souci avec while (tmp2 /* test tmp2 existe */){tmp2 = tmp2->suivant /* positionnement sur son suivant */; if (tmp->donnee > tmp2->donnee /* examen du contenu du suivant sans vérifier son existence !!! */) ...). Et les 5% restant c'est juste de l'habitude.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 7
    Dernier message: 21/11/2012, 12h40
  2. Liste chainée & Erreur de segmentation
    Par max0u13 dans le forum Débuter
    Réponses: 3
    Dernier message: 13/03/2012, 10h56
  3. Réponses: 4
    Dernier message: 27/04/2009, 19h33
  4. Liste Chainée -> Pointer Exception Erreur
    Par pingouinos_64 dans le forum Général Java
    Réponses: 1
    Dernier message: 26/02/2009, 23h40
  5. Fin de liste chainée, erreur
    Par faulk dans le forum C
    Réponses: 3
    Dernier message: 21/10/2006, 20h02

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