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 :

Liste simplement chainée


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    on définit une structure supplémentaire est est la liste.
    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;
    };
    Ce que tu appelais 'liste' est en fait un 'node'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct node
    {
       struct node *p_next;
       /* data ... */
    };
    Les fonctions gèrent alors les deux pointeurs (début et fin). Le pointeur de fin permet d'accélerer le traitement (plus besoin de faire une boucle pour ajouter en fin)...

    Maintenant, tous devient simple et clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    /* evidemment, il ne vaut pas oublier ca ! */
       struct list Liste = {0}; 
     
       ajouter(&Liste, 123);
       ajouter(&Liste, 456);
       ajouter(&Liste, 789);
    Alors j'ai quelques questions avant d'attaquer le code :
    la structure list, ne sert qu'à repérer le debut et la fin de ma liste ?
    mon ancienne structure devient comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct node {
       struct node *suivant;
       int val;
    }
    que fait cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct list Liste = {0};
    J'ai un peu de mal à debuter, j'espere que les réponses me le permettront. Merci pour ton aide

  2. #2
    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 sorry60
    la structure list, ne sert qu'à repérer le debut et la fin de ma liste ?
    Oui, et c'est essentiel. Tu perds ça, t'es mort!
    mon ancienne structure devient comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct node {
       struct node *suivant;
       int val;
    }
    Oui.
    que fait cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct list Liste = {0};
    Elle définit une structure et met tous ses élements à 0. Comme se sont des pointeurs, ça va faire NULL.

    Je sais que tu vas y arriver.

  3. #3
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    Voila mon nouveau code :

    Le header :
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct node {
    	struct node *pSuivant;
    	int val;
    }node;
     
    typedef struct list {
    	struct node *pTete;
    	struct node *pQueue;
    }list;
     
    /* Fonction qui ajoute un élément en fin de liste */
    node* ajouter(node *p,int valeur);
    Le .c avec la fonction d'ajout :
    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
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif
     
    #include "liste.h"
     
    /* Fonction qui ajoute un élément en fin de liste */
    node* ajouter(node *p,int valeur)
    {
    	node *nouv = malloc(sizeof(*nouv));
     
    	if(nouv)
    	{
    		nouv->val = valeur;
    		nouv->pSuivant = NULL;
    		/* On teste si la liste est vide */
    		if( !p )
    		{
    			/* On ajoute directement le nouvel element */
    			p = nouv;
    		}
    		else
    		{
    			/* On parcourt la liste jusqu'au dernier element */
    			while(p->pSuivant)
    			{
    				p = p->pSuivant;
    			}
    			/* On insere le nouvel element */
    			p->pSuivant = nouv;
    		}
    	}
    	else
    	{
    		perror("malloc()");
    		exit(1);
    	}
    	return p;
    }
    Et le main :
    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
     
    #ifdef __cplusplus
    #error Be sure you are using a C compiler...
    #endif
     
    #include "liste.h"
     
    int main()
    {
    	/* notre pointeur sur une liste bientot chainée ! */
    	list* pMaListe = {0};
     
    	/* On ajoute quelques elements */
    	pMaListe = ajouter(pMaListe,1);
    	system("Pause");
    	return 0;
    }
    La compil' passe impect, je pense que le code est correct. Par contre je ne vois pas comment récuperer la tete et la queue
    En faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    list *pDebMaListe = pMaListe->pTete;
    :

    Edit : ce code ne compile pas, car à ajouter je passe un list* au lieu d'un *node, mais comme je ne comprend pas, je prefere le mettre, histoire de ne pas cacher mon ignorance

  4. #4
    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 sorry60
    Voila mon nouveau code :
    <...>
    La compil' passe impect, je pense que le code est correct.
    Pas du tout. La conception n'est pas bonne.

    L'interface de la fonction est maintenant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p, int valeur);
    Tout le reste doit être modifié en conséquence.

    Et les pointeurs pTete et pQueue ne vont pas bouger tout seuls...

    J'ai ceci qui fonctionne :
    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
     
    #include "liste.h"
     
    int main()
    {
    	/* notre pointeur sur une liste bientot chainée ! */
     
    	struct list MaListe = {0};
     
    	/* On ajoute quelques elements */
    	ajouter (&MaListe, 1);
    	ajouter (&MaListe, 2);
    	ajouter (&MaListe, 3);
     
    	afficher (&MaListe);
     
    	liberer (&MaListe);
     
    	return 0;
    }
    Je te laisse compléter les fichiers liste.h et liste.c.

    Ca donne ça :

  5. #5
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    J'avoue que j'ai beaucoup de mal à saisir le truc
    Voici le main :
    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
     
    int main()
    {
    	/* notre pointeur sur une liste bientot chainée ! */
    	list maListe = {0};
     
    	/* On ajoute quelques elements */
    	ajouter(&maListe,1);
    	ajouter(&maListe,2);
    	ajouter(&maListe,3);
     
    	/* On affiche */
    	afficher(&maListe);
     
    	system("Pause");
    	return 0;
    }
    Le .h :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct node {
    	struct node *pSuivant;
    	int val;
    }node;
     
    typedef struct list {
    	struct node *pTete;
    	struct node *pQueue;
    }list;
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p,int valeur);
    /* Fonction qui affiche la liste chainée */
    void afficher(list *p);
    Et le code des fonctions d'ajout et d'affichage :
    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
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p,int valeur)
    {
    	list *nouv = malloc(sizeof(*nouv));
     
    	if(nouv)
    	{
    		nouv->pTete->val = valeur;
    		nouv->pTete->pSuivant = NULL;
    		nouv->pQueue = NULL;
    		/* On teste si la liste est vide */
    		if( !p )
    		{
    			/* On ajoute directement le nouvel element */
    			p = nouv;
    		}
    		else
    		{
    			/* On parcourt la liste jusqu'au dernier element */
    			while(p->pTete->pSuivant)
    			{
        			p->pTete = p->pTete->pSuivant;
    			}
    			/* On insere le nouvel element */
    			p = nouv;
    		}
    	}
    	else
    	{
    		perror("malloc()");
    		exit(1);
    	}
    }
     
    /* Fonction qui affiche la liste chainée */
    void afficher(list *p)
    {
    	while(p->pTete)
    	{
    		printf("%d\n",p->pTete->val);
    		p->pTete = p->pTete->pSuivant;
    	}
    }
    A la compil' j'ai deux warnings :
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] missing initializer
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] (near initialization for `maListe.pQueue')
    Pour la ligne :
    Et à l'execution, une erreur d'ecriture en zone mémoire protégée (je m'en doutais..).

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

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Par défaut
    Toujours le même problème sur les pointeurs : si tu veux que le pointeur soit modifié au retour de la fonciton, donne l'adresse de ce pointeur.
    donc :
    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
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list **p,int valeur)
    {
       list *nouv = malloc(sizeof(*nouv));
     
       if(nouv)
       {
          nouv->pTete->val = valeur;
          nouv->pTete->pSuivant = NULL;
          nouv->pQueue = NULL;
          /* On teste si la liste est vide */
          if( !(*p) )
          {
             /* On ajoute directement le nouvel element */
             *p = nouv;
          }
          else
          {
             /* On parcourt la liste jusqu'au dernier element */
             list *tmp = *p;
             while(tmp->pTete->pSuivant)
             {
                 tmp->pTete = tmp->pTete->pSuivant;
             }
             /* On insere le nouvel element */
             tmp = nouv;
          }
       }
       else
       {
          perror("malloc()");
          exit(1);
       }
    }
    Il aurait d'ailleurs été meilleur que ta fonction retourne un pointeur list *.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

  7. #7
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    J'essaye d'eviter les ** pour le moment vu que je debute avec les listes
    Donc je m'eforce de suivre ce que me dis Emmanuel Delaye :
    Citation Envoyé par Emmanuel Delahaye
    L'interface de la fonction est maintenant
    Code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p, int valeur);
    Mais je me perd un peu dans toutes ces structures...et je ne vois pas comment faire bouger la tete de la liste

  8. #8
    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 sorry60
    J'avoue que j'ai beaucoup de mal à saisir le truc
    Y'a pas de 'truc'. C'est de la programmation la plus simple et directe qu'il soit...
    Voici le main :
    <...>
    Le .h :
    <...>
    Jusque là, ça va, à part ce commentaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	/* notre pointeur sur une liste bientot chainée ! */
    Je ne vois pas de pointeur, mais une structure.
    Et le code des fonctions d'ajout et d'affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p,int valeur)
    {
    	list *nouv = malloc(sizeof(*nouv));
     
    	if(nouv)
    	{
    		nouv->pTete->val = valeur;
    		nouv->pTete->pSuivant = NULL;
    		nouv->pQueue = NULL;
    		/* On teste si la liste est vide */
    		if( !p )
    NON. La liste est vide si p->pTete vaut NULL.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    		{
    			/* On ajoute directement le nouvel element */
    			p = nouv;
    Et il faudrait peut être mettre à jour p->pTete et p->pQueue, non ? Ca va pas se faire tout seul.

    C'est pas compliqué. On a collé les deux pointeurs pTete et pQueue dans une une structure liste. Les fonctions de listes sont là pour gérer ces pointeurs (initialisation, mise à jour, lecture). Je ne vois pas ce qu'il y a de compliqué.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    		}
    		else
    		{
    			/* On parcourt la liste jusqu'au dernier element */
    NON. Il suffit de lire p->pQueue. Evidemment il faut qu'il soit à jour... C'est justement pour éviter cette boucle qu'on a crée pQueue. C'est si difficile à comprendre ?

    Par contre, il faire le lien et mettre a jour le pointeur de fin (pQueue). Tu as fait le schéma comme je te l'ai demandé ?
    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
     
    			while(p->pTete->pSuivant)
    			{
        			p->pTete = p->pTete->pSuivant;
    			}
    			/* On insere le nouvel element */
    			p = nouv;
    		}
    	}
    	else
    	{
    		perror("malloc()");
    		exit(1);
    	}
    }
     
    /* Fonction qui affiche la liste chainée */
    void afficher(list *p)
    {
    	while(p->pTete)
    NON ! Il faut utiliser un pointeur local. Pour lire un objet, on a pas le droit de le modifier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void afficher(list const *p)
    évite les bétises...

    D'ailleurs, j'avais écrit (je ne retrouve plus l'original) un truc du genre :
    Citation Envoyé par -ed-
    Dans une liste chainée, le pointeur de tête est essentiel. Si tu le perd, t'es mort!
    Or là, tu le modifies sans vergogne.

  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 Trap D
    Toujours le même problème sur les pointeurs : si tu veux que le pointeur soit modifié au retour de la fonciton, donne l'adresse de ce pointeur.
    donc :
    [code]/* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list **p,int valeur)
    Argh! Tu n'as pas suivit tous les épisodes. Maintenant on a une structure liste qui évite ce genre de sport.

    M'enfin, c'est si compliqué que ça d'écrire du code simple ?

  10. #10
    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 sorry60
    Citation Envoyé par Emmanuel Delahaye
    L'interface de la fonction est maintenant
    Code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p, int valeur);
    Mais je me perd un peu dans toutes ces structures...
    Gné ? Il n'y a que 2 structures !

    list et node.

    list a les deux pointeurs tete et queue. node a les chainages (suivant) et les données. Tu l'as enfin fait ce schéma, ou je parle aux murs ?
    et je ne vois pas
    comment faire bouger la tete de la liste
    Ca se passe une fois lors de l'ajout du premier élément.

    FAIT LE SCHEMA

  11. #11
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Gné ? Il n'y a que 2 structures !

    list et node.

    list a les deux pointeurs tete et queue. node a les chainages (suivant) et les données. Tu l'as enfin fait ce schéma, ou je parle aux murs ?
    et je ne vois pas
    comment faire bouger la tete de la liste
    Ca se passe une fois lors de l'ajout du premier élément.

    FAIT LE SCHEMA
    J'y vais, là je revisais un peu mon assembleur pour demain.
    Merci pour tes explications, je vais faire ce fameux schema

  12. #12
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    J'ai fait un schéma, j'espere qu'il est bon..je vais essayer de le redessiner ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Avant tout ajout :
       pTete -> NULL
       pQueue -> NULL
     
    Apres un ajout :
       pTete et pQueue -> nouv1 -> NULL
     
    Encore un ajout :
       pTete -> nouv1 -> nouv2 -> NULL
       pQueue -> nouv2
    Ce qui me mène au code suivant pour la fonction d'ajout :
    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
     
    void ajouter(list *p,int valeur)
    {
    	node nouv;
    	nouv.val = valeur;
    	nouv.pSuivant = NULL;
    	/* Si la liste est vide */
    	if( !p->pTete )
    	{
    		/* Le nouvel element est à la fois tete et queue */
    		p->pTete = &nouv;
    		p->pQueue = &nouv;
    	}
    	else
    	{
    		/* La liste n'est pas vide, le dernier élément est pQueue */
    		p->pQueue = &nouv;
    		p->pTete->pSuivant = p->pQueue;
    	}
    }
    Vai-je encore récolter les foudres d'Emmanuel ?

  13. #13
    Membre chevronné Avatar de Jack_serious
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    350
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 350
    Par défaut
    Fais gaffe !

    d'apres ton code, nouv est une variable locale !

    Fais un malloc, sinon ton nouvel element va disparaitre dans les profondeurs intersiderales de l'insondable des la sortie de ta fonction...

    Pour le reste, il y a du mieux mais c'est encore un peu bancal. M'est avis que tu te complique la vie pour rien.

    Le pointeur pTete a besoin d'etre initialise une seule fois (deux en fait, mais je ne compte pas la mise a NULL) : lors de l'ajout du premier element.

    Par la suite, il suffit de faire pointer pQueue sur l'element que tu viens d'ajouter.

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut
    un seul petit problème dans ta fonction ajouter. il te faut utiliser un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    node * nouv;
    nouv = malloc(sizeof(*nouv));
    sinon la variable est détruite à la sortie de ta fonction.
    Ensuite si tu ajoutes dans liste non vide alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    p->pQueue->pSuivant = nouv;
    p->pQueue=nouv;
    Stef

  15. #15
    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 sorry60
    J'ai fait un schéma, j'espere qu'il est bon..je vais essayer de le redessiner ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Avant tout ajout :
       pTete -> NULL
       pQueue -> NULL
     
    Apres un ajout :
       pTete et pQueue -> nouv1 -> NULL
     
    Encore un ajout :
       pTete -> nouv1 -> nouv2 -> NULL
       pQueue -> nouv2
    AAAAHHH!
    Ca va tout de suite aller mieux, non ?
    Ce qui me mène au code suivant pour la fonction d'ajout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void ajouter(list *p,int valeur)
    {
    	node nouv;
    ARG! Ou est passé le malloc () ?
    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
     
    	nouv.val = valeur;
    	nouv.pSuivant = NULL;
    	/* Si la liste est vide */
    	if( !p->pTete )
    	{
    		/* Le nouvel element est à la fois tete et queue */
    		p->pTete = &nouv;
    		p->pQueue = &nouv;
    	}
    	else
    	{
    		/* La liste n'est pas vide, le dernier élément est pQueue */
    		p->pQueue = &nouv;
    		p->pTete->pSuivant = p->pQueue;
    	}
    }
    Vai-je encore récolter les foudres d'Emmanuel ?
    A ton avis ?

    Mais pourquoi as-tu retiré le malloc() ? Depuis quand une variable locale est-elle persistante après la fonction ?

    Le reste, c'est presque ça, mais tu t'emmelles dans les chainages...

    La liste n'est pas vide :
    1 - On utilise le pointeur de queue pour mettre à jour le chainage
    2 - On met à jour le pointeur de queue.

    Pour cette opération on a jamais besoin du pointeur de tête.

    Integre tout ça dans ton code, et tu y es.

  16. #16
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Mais pourquoi as-tu retiré le malloc() ? Depuis quand une variable locale est-elle persistante après la fonction ?

    Le reste, c'est presque ça, mais tu t'emmelles dans les chainages...

    La liste n'est pas vide :
    1 - On utilise le pointeur de queue pour mettre à jour le chainage
    2 - On met à jour le pointeur de queue.

    Pour cette opération on a jamais besoin du pointeur de tête.

    Integre tout ça dans ton code, et tu y es.
    Oui en effet je sais pas pourquoi j'ai enlevé le malloc
    De plus mon rechainage n'etait pas top car en mettant 2 éléments ça marchait bien mais pas pour plus..
    J'ai donc refais un schema pour l'ajout de plus d'elements et j'ai corrigé mon erreur.
    Voici le code final des fonctions d'ajout et d'affichage :
    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
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p,int valeur)
    {
    	node *nouv = malloc(sizeof(*nouv));
    	nouv->val = valeur;
    	nouv->pSuivant = NULL;
    	/* Si la liste est vide */
    	if( !p->pTete )
    	{
    		/* Le nouvel element est à la fois tete et queue */
    		p->pTete = nouv;
    		p->pQueue = nouv;
    	}
    	else
    	{
    		/* La liste n'est pas vide, le dernier élément est pQueue */
    		p->pQueue->pSuivant = nouv;
    		p->pQueue = nouv;
     
    	}
    }
     
    /* Fonction qui affiche la liste chainée */
    void afficher(list const *p)
    {
    	node *tmp = p->pTete;
    	while ( tmp )
    	{
    		printf("%d\n",tmp->val);
    		tmp = tmp->pSuivant;
    	}
    }
    J'attend le tampon avant d'attaquer la suppression

    Edit : il y a toujours ces deux warnings persistants :
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] missing initializer
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] (near initialization for `maListe.pQueue')
    Pour la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* notre liste bientot chainée ! */
    	list maListe = {0};

  17. #17
    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 sorry60
    Oui en effet je sais pas pourquoi j'ai enlevé le malloc
    Voici le code final des fonctions d'ajout et d'affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    /* Fonction qui ajoute un élément en fin de liste */
    void ajouter(list *p,int valeur)
    {
    	node *nouv = malloc(sizeof(*nouv));
    Ouiiinnn ! Et le test si malloc() echoue ? Tu as détruit du code qui était bon. Pourquoi ? Accès de mauvaise humeur ?
    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
     
    	nouv->val = valeur;
    	nouv->pSuivant = NULL;
    	/* Si la liste est vide */
    	if( !p->pTete )
    	{
    		/* Le nouvel element est à la fois tete et queue */
    		p->pTete = nouv;
    		p->pQueue = nouv;
    	}
    	else
    	{
    		/* La liste n'est pas vide, le dernier élément est pQueue */
    		p->pQueue->pSuivant = nouv;
    		p->pQueue = nouv;
    OK
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    	}
    }
     
    /* Fonction qui affiche la liste chainée */
    void afficher(list const *p)
    {
    	node *tmp = p->pTete;
    	while ( tmp )
    	{
    		printf("%d\n",tmp->val);
    		tmp = tmp->pSuivant;
    OK
    J'attend le tampon avant d'attaquer la suppression

    Edit : il y a toujours ces deux warnings persistants :
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] missing initializer
    10 C:\Documents and Settings\Thomas\Mes documents\Langage C\Exercices\Listes\SimplementChainée\main.c [Warning] (near initialization for `maListe.pQueue')
    Pour la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* notre liste bientot chainée ! */
    	list maListe = {0};
    Il y a deux élements. gcc qui est plutôt 'picky' la-dessus, demande que tous les élements soient initialisés (ce qui va au-dela de la norme)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* notre liste bientot chainée ! */
    	list maListe = {NULL, NULL};
    pour etre cohérent.

  18. #18
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    J'ai remis le test du retour de malloc().
    J'attaque la fonction retirer.

    Merci beaucoup pour ton aide

  19. #19
    Membre éclairé Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Par défaut
    Voila ma fonction qui retire un élément precis.
    Je l'ai testé, ça a l'air d'etre bon.


    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
    /* Fonction qui retire un element precis */
    void retirer(list *p, int valeur)
    {
    	/* Si la liste est vide...*/
    	if( !p->pTete )
    	{
    		printf("La liste est vide !\n");
    		return;
    	}
    	/* Si l'element à retirer est le seul de la liste */
    	if( (!p->pTete->pSuivant) && (p->pTete->val == valeur))
    	{
    		free(p->pTete);
    		free(p->pQueue);
    		p->pTete = NULL;
    		p->pQueue = NULL;
    	}
    	else
    	{
    		node *tmp = p->pTete;
    		node *prec = malloc(sizeof(*prec));
    		if(prec)
    		{
    			/* On se positionne sur le bon element */
    			while ( tmp && (tmp->val != valeur) )
    			{
    				prec = tmp;
    				tmp = tmp->pSuivant;
    			}
    			/* Si l'element a été trouvé */
    			if ( tmp != NULL )
    			{
    				/* on rechaine sans l'element a supprimer */
    				prec->pSuivant = tmp->pSuivant;
    				/* on supprime l'element */
    				free(tmp);
    			}
    			else
    			{
    				printf("Element absent !\n");
    			}
    		}
    		else
    		{
    			perror("malloc()");
    			exit(1);
    		}
    	}
    }
    Le main :
    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
    int main()
    {
    	/* notre liste bientot chainée ! */
    	list maListe = {0};
     
    	/* On ajoute quelques elements */
    	ajouter(&maListe,1);
    	ajouter(&maListe,2);
    	ajouter(&maListe,3);
    	ajouter(&maListe,4);
    	ajouter(&maListe,5);
    	/* On affiche */
    	printf("Avant :\n");
    	afficher(&maListe);
    	/* On le retire */
    	retirer(&maListe,3);
    	/* On affiche */
    	printf("Apres :\n");
    	afficher(&maListe);
    	system("Pause");
    	return 0;
    }
    Donne :
    Avant :
    1
    2
    3
    4
    5
    Apres :
    1
    2
    4
    5
    Appuyez sur une touche pour continuer...
    "Lu et approuvé" : :

  20. #20
    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 sorry60
    Voila ma fonction qui retire un élément precis.
    Je l'ai testé, ça a l'air d'etre bon.
    <...>
    "Lu et approuvé" : :
    Non. Il y a un problème de libération.

    Avec ce main():

    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
    int main()
    {
       list maListe = {0, 0};
     
       /* On ajoute quelques elements */
       ajouter(&maListe,1);
       ajouter(&maListe,2);
       ajouter(&maListe,3);
     
       /* On affiche */
       printf("Avant :\n");
       afficher(&maListe);
     
       /* On le retire */
       printf("On retire 2 :\n");
       retirer(&maListe,2);
       /* On affiche */
       afficher(&maListe);
     
       printf("On retire 3 :\n");
       retirer(&maListe,3);
       /* On affiche */
       afficher(&maListe);
     
       printf("On retire 1 :\n");
       retirer(&maListe,1);
       /* On affiche */
       afficher(&maListe);
     
       return 0;
    }
    On obtient :
    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
     
    Avant :
    1
    2
    3
    On retire 2 :
    1
    3
    On retire 3 :
    1
    On retire 1 :
    <...>
    SYSALLOC Bloc 003D24D8 freed at line 66 of 'liste.c' not allocated
    SYSALLOC Bloc 003D24C8 (8 bytes) malloc'ed at line 73 of 'liste.c' not freed
    SYSALLOC Bloc 003D24E8 (8 bytes) malloc'ed at line 73 of 'liste.c' not freed
    Tu me fais un malloc() dans retirer() ? Pourquoi ? C'est le dernier endroit où on doit voir du malloc(). Du free(), oui, mais certainement pas de malloc().

    Et quand il n'y a plus qu'un seul élément, tu fais deux free() ! Il y en a forcément un de trop, puisque il ne reste plus qu'un élément !

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. problème liste simplement chainée
    Par cyrill.gremaud dans le forum C
    Réponses: 9
    Dernier message: 04/12/2012, 15h40
  2. fusion de deux liste simplement chainée
    Par mdh12 dans le forum Débuter
    Réponses: 6
    Dernier message: 14/01/2010, 19h23
  3. Tri d'une pile avec liste simplement chainée
    Par thecabbages dans le forum C
    Réponses: 3
    Dernier message: 17/12/2009, 21h08
  4. question liste simplement chainée
    Par american dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 15/03/2009, 21h45
  5. Réponses: 3
    Dernier message: 25/10/2006, 19h08

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