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 :

Problème avec les piles (chaînées)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 12
    Par défaut Problème avec les piles (chaînées)
    Bonsoir, j'en ai eu tellement marre de ne pas trouver mon erreur que je viens demander au secours ici !
    J'ai voulu faire un peu de C pour me remettre d'aplomb, en commençant par une truc "basique", les piles.

    Dans le doute je vais poster tout le code puis j'expliquerai mon problème ^^
    J'ai fais un .c, un .h et un 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
    32
     
     
    //pile.h 
     
    #ifndef _PILE_H_
    #define _PILE_H_
    #include <stdio.h>
    #include <stdbool.h>
     
     
    typedef struct s_pile Pile;
    typedef struct s_element Element;
     
    Pile *creerPile();
     
    void supprimerPile (Pile *p);
     
    Pile *viderPile (Pile *p);
     
    void *sommet (Pile *p);
     
    void empiler (Pile *p, void* e);
     
    void* depiler (Pile *p);
     
    bool vide (Pile *p);
     
    size_t taille (Pile *p);
     
    void afficherGeneral (Pile *p, void (*affSpec)(void *e));
     
    #endif

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    //pile.c
     
    #include "pile.h"
    #include <assert.h>
    #include <stdlib.h>
     
     
    struct s_element {
    	void* valeur;
    	struct s_element *suivant;
    };
     
     
    struct s_pile {
    	Element *sommet;
    	size_t taille;
    };
     
     
    Pile *creerPile() {
    	Pile *p  = malloc(sizeof(struct s_pile));
    	p->sommet = NULL;
    	p->taille = 0;
    	return p;
    }
     
     
    void supprimerPile (Pile *p) {
    	Element *aSuppr = p->sommet;
    	while (aSuppr) {
    		Element *f = aSuppr;
    		aSuppr = aSuppr->suivant;
    		free(f);
    	}
    	free(p);
    	p=NULL;
    }
     
     
    bool vide (Pile *p) {
    	return (p->taille == 0);
    }
     
     
    Pile *viderPile (Pile *p) {
    	if (vide(p))
    		return p;
    	Element *aSuppr = p->sommet;
    	while (aSuppr) {
    		Element *f = aSuppr;
    		aSuppr = aSuppr->suivant;
    		free(f);
    	}
    	p->sommet = NULL;
    	p->taille = 0;
    	return p;
    }
     
    void *sommet (Pile *p) {
    	if (vide(p)) {
    		printf("La pile est vide !\n");
    		exit(1);
    	}
    	return (p->sommet->valeur);
    }
     
     
    size_t taille (Pile *p) {
    	return p->taille;
    }
     
     
    void empiler (Pile *p, void* e) {
    	Element *nouveauSommet = (Element *)malloc(sizeof(Element));
    	nouveauSommet->valeur = e;
    	nouveauSommet->suivant = p->sommet;
    	p->sommet = nouveauSommet;
    	p->taille ++;
    }
     
     
    void* depiler (Pile *p) {
    	assert (!vide(p));
    	Element *suppr = p->sommet;
    	p->sommet = p->sommet->suivant;
    	void* e = suppr->valeur;
    	free(suppr);
    	p->taille --;
    	return e;
    }
     
     
    void afficherGeneral (Pile *p, void (*affSpec)(void *e)) {
    	printf("Taille de la pile : %ld\n", p->taille);
    	while (p->sommet != NULL) {
    		affSpec(p->sommet->valeur);
    		p->sommet = p->sommet->suivant;
    	}
     
    }


    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
     
    //main.c
    #include "pile.h"
    #include <stdlib.h>
     
    void afficher (void* e) {
    	printf("%d\n", *(int*)e);
    }
     
     
    int main()
    {
     
    	Pile *p = creerPile();
     
        int *i = (int*)malloc(sizeof(int));
        *i=0;
        empiler(p,i);
        *i=1;
        empiler(p,i);
        *i=2;
        empiler(p,i);
        *i=3;
        empiler(p,i);
     
        afficherGeneral (p, afficher);
     
        return 0;
    }


    L'exécution du main me donne :
    Taille de la pile : 4
    3
    3
    3
    3

    en gros j'ai mon sommet qui est affiché 4 fois.
    J'ai testé pleins de main, j'ai rajouté des fonctions intermédiaires et fait pleins d'affichages au fur et à mesure, et au fur et à mesure de mon empiler j'ai bien le sommet qui prend la valeur de 0, puis 1, 2 et 3. Avec des fonctions intermédiaires pour afficher le suivant, le suivant du suivant,... , je constate que le suivant prend la valeur de mon nouveau sommet (j'ai pourtant l'impression de le faire dans le bon sens dans le code), et tous les autres suivants prennent cette valeur. Ou alors mon affiche est mauvais mais je ne vois pas comment faire autrement.

    Merci d'avoir pris le temps de me lire et de prendre le temps de me répondre, bonne continuation à vous et bon courage pour comprendre mon erreur (qui doit etre toute bête comme 95% des erreurs en programmation ) !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 599
    Par défaut
    Bonjour,

    Tu as empilé 4 fois le même pointeur i. Donc tu as bien 4 fois la même chose.
    En écrivant *i=42; et affiche ta pile, elle contiendra 4 fois le même pointeur sur 42.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 12
    Par défaut
    Aaaaah !! je me disais bien que c'était une erreur débile XD

    bah merci beaucoup, mais du coup je ne vois pas trop comment faire car je dois rentrer un void *, comment je peux entrer un int sans faire comme je fais et sans créer un nouveau pointeur à chaque fois alors ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 599
    Par défaut
    Telles que tu les a écrites, tes fonctions s'attendent un pointeur void* qu'elles ne gèrent pas dynamiquement (ni allocation ni désallocation). Donc pas d'autre possibilité que de lui passer un pointeur différent à chaque insertion. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        double tabi[] = { .0, .5, 1., 1.5, 2., 2.5 }; // c'est le "propriétaire" des données
        empiler( p , &tabi[0] );
        empiler( p , &tabi[1] );
        empiler( p , &tabi[2] );
     
        afficherGeneral(p, afficherDouble);
    On peut sinon considérer que la liste est "propriétaire" des données. Dans ce cas elle doit gérer les allocations et désallocations mais à besoin de connaître au moins la taille du pointé.
    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
    bool empiler( Pile *ppile , void* e , size_t taille ) {
    	Element* nouveauSommet = malloc( sizeof(Element) );
            if ( nouveauSommet == NULL ) return false; // mémoire insuffisante
    	nouveauSommet->valeur = malloc( taille );
            if ( nouveauSommet->valeur == NULL ) return false; // mémoire insuffisante
            memcpy( nouveauSommet->valeur , e , taille );
    	nouveauSommet->suivant = ppile->sommet;
    	ppile->sommet = nouveauSommet;
    	++ppile->taille;
            return true;
    }
    ... ... ...
        float x;
        x=0.f; empiler( p, &x, sizeof x );
        x=1.f; empiler( p, &x, sizeof x );
        x=2.f; empiler( p, &x, sizeof x );
     
        afficherGeneral( p, afficherFloat );
    On peut aussi "optimiser" ce dernier cas car on fait toujours une allocation pour le sommet et une allocation pour la donnée. On pourrait définir un sommet qui serait alloué en même temps que sa donnée pour n'avoir qu'un malloc() (et donc un seul free() à la libération.)

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 12
    Par défaut
    Ah oui je vois, je n'avais jamais utilisé de void* et je n'étais pas sûr de son fonctionnement, c'est logique en fait x)
    Bon bah merci de ton aide, bonne continuation

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

Discussions similaires

  1. probléme avec les piles
    Par dev_2007 dans le forum Débuter
    Réponses: 12
    Dernier message: 16/11/2008, 23h13
  2. Problème avec les piles
    Par ouchemhou dans le forum Débuter
    Réponses: 1
    Dernier message: 13/05/2008, 23h05
  3. Problème avec les listes chaînées
    Par yous18 dans le forum C
    Réponses: 38
    Dernier message: 25/10/2007, 22h30
  4. Réponses: 4
    Dernier message: 03/01/2007, 21h25
  5. [TP 7] Problème avec les listes chaînées (error 202)
    Par thelinekioubeur dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 06/12/2006, 23h15

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