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 :

afficher une pile en POO


Sujet :

C++

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut afficher une pile en POO
    Bonjour,
    sil vous plait je fais de la POO
    j'essai sans succès d'afficher une pile en C++
    Dans mon fichier .h j'ai declaré void Afficher(elt *lapile);
    Dans mon fichier .cpp j'ai declaré void pile::Afficher(elt *lapile);
    Dans mon Programme principal j'ecris (*une_pile).Afficher(une_pile);
    quand je compile j'ai comme erreur
    9 C:\Users\Achille\Documents\mes docs\c++\une_pile\unepile.cpp no matching function for call to `pile::Afficher(pile*&)'
    note C:\Users\Achille\Documents\mes docs\c++\une_pile\pile.h:21 candidates are: void pile::Afficher(elt*)
    MERCI de m'aider

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut, et bienvenue sur le forum.

    Il "suffit" pourtant de lire le message d'erreur, pour autant que l'on comprenne l'anglais de base.

    Le compilateur se plaint de ne trouver aucune fonction Afficher prenant comme paramètre un pointeur sur un objet de type pile et t'avertit que le candidat qu'il a trouvé demande... un pointeur sur un objet de type elt comme argument

    Ceci dit, si tu veux une aide plus efficace, il est généralement intéressant de nous passer un code minimum compilable reproduisant le problème, car Madame Irma est partie aux sports d'hiver, et on ne sait pas quand elle rentrera (en plus, j'ai entendu dire que sa boule de crystal est en panne )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre régulier
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 120
    Points
    120
    Par défaut
    Une question me turlupine :

    Quelle est l'utilité de passer une pile en paramètre à ta fonction afficher qui est déjà une fonction de la classe pile?

    D'ailleurs on voit bien qu'il y'a redondance dans ton code.

    (*une_pile).Afficher(une_pile);
    Enfin, j'aime pas cette écriture (même si elle est tout à fait correcte)
    (*une_pile).Afficher
    Je lui préfére :

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lcfseth Voir le message
    Une question me turlupine :

    Quelle est l'utilité de passer une pile en paramètre à ta fonction afficher qui est déjà une fonction de la classe pile?

    D'ailleurs on voit bien qu'il y'a redondance dans ton code.



    Enfin, j'aime pas cette écriture (même si elle est tout à fait correcte)

    Je lui préfére :
    Il y a cela aussi, mais, alors, si on part sur ce terrain on est très largement en droit de se demander pourquoi passer par un pointeur...

    Et seul le code complet est en mesure de nous permettre de traquer les erreurs de ce genre
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre régulier
    Inscrit en
    Septembre 2007
    Messages
    114
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 114
    Points : 120
    Points
    120
    Par défaut
    Si je devais deviner, je dirais que c'est des résidu de C. Mais bon comme tu dis, un bout de code serait le bien venu.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut
    Voici le code de ma methode afficher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void pile :: Afficher( elt *lapile)
     { elt *p;
        p=lapile;
        while(p!=NULL)
        { cout<<"\nLa valeur  est \n"<< (*p).valeur;
        p=(*p).suivant;
      }
     }

    il faut bien que j lui passe un parametre pour qu' elle affiche

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par patricx Voir le message
    Voici le code de ma methode afficher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void pile :: Afficher( elt *lapile)
     { elt *p;
        p=lapile;
        while(p!=NULL)
        { cout<<"\nLa valeur  est \n"<< (*p).valeur;
        p=(*p).suivant;
      }
     }

    il faut bien que j lui passe un parametre pour qu' elle affiche
    Non, pas si tu as travaillé un temps soit peu correctement...

    En toute logique, ta pile dispose comme membre privé d'un... pointeur vers le dernier élément ajouté...

    Or, et c'est là toute la "beauté" de l'orienté objet, lorsque tu invoque une fonction sur un objet donné, la fonction connait l'ensemble de ce qui compose l'objet en cours grâce à un paramètre fournit de manière implicite (comprend: sans qu'il ne soit nécessaire de l'indiquer toi-même) : this.

    Cela implique que tu peux, dans une fonction membre appeler this->quelque_chose et être sur que le quelque_chose en question appartient bel et bien à l'objet courent.

    Mieux encore, this est à ce point implicite dans la fonction que tu peux même utiliser directement le membre (qu'il s'agisse d'une variable ou d'une fonction) qui t'intéresse sans avoir à le préciser : si tu essaye d'accéder "simplement" à quelque_chose, c'est strictement similaire à un accès à this->quelque_chose.

    La seule chose à laquelle tu doive être attentif, dans le cas de ta pile, c'est à ne pas "perdre" le pointeur sur le dernier élément réel de la pile, si, comme ton code semble l'indiquer, tu n'envisages pas de vider ta pile à l'affichage.

    Ainsi, ta fonction Afficher pourrait prendre la forme toute simple de
    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
    void Pile::Afficher()
    {
        /* pour ne pas risquer de perdre les éléments de la pile, nous avons
         * besoin d'un pointeur de travail vers l'élément à traiter
         * 
         * Nous l'initialisons directement avec... la valeur du dernier élément
         * de la pile
         */
        elt* travail = last;
        while(travail)
        {
            cout<<"blabla "<<travail->valeur;
            travail=travail->suivant;
        }
    }
    Je voudrais cependant faire une ou deux remarques sur les problèmes que ce code (qui n'est toujours pas suffisant pour reproduire le problème que tu nous expose...) met en évidence.

    La première est que tu devrais prendre l'habitude de choisir une politique d'indentation stricte et de t'y tenir en permanence.

    Il faut, en effet, être bien conscient du fait qu'un code est beaucoup plus souvent lu / étudié qu'il n'est modifié...

    Et, si je ne doutes absolument pas que ton code te semble parfaitement clair, là, à l'instant, alors que tu l'as écrit hier soir, il risque de te sembler beaucoup moins évident dans une semaine, un mois ou un an... Enfin de manière générale, quand tu aura eu l'occasion d'oublier ce qu'il est sensé faire.

    Et c'est encore pis lorsqu'il s'agit d'étudier un code... que tu n'as pas écrit toi-même...

    Il est donc primordial de veiller à ce que ton code garde une qualité que je n'hésite pas à faire passer avant même le fait de faire ce que l'on attend de lui : être facilement lisible et compréhensible.

    Quelques règles simples suffisent pour obtenir ce résultat, sans que cela n'ait le moindre impact sur les performances:
    • ne mettre qu'une instruction par ligne
    • respecter une politique stricte et cohérente d'indentation (tu remarquera que tout ce qui est à un même niveau d'imbrication dans mon code commence exactement au même endroit dans la ligne)
    • utiliser des noms (de type, de fonction ou de variable) clairs et explicites

    Tes noms sont clairs, mais le type elt serait sans doute avantageusement remplacé par... element, et le nom du paramètre que tu donne pourrait facilement devenir... elem (enfin, s'il était nécessaire).

    Pense à initialiser tes pointeurs au moment où tu les déclares. Cela peut t'éviter bien des problèmes dont il est parfois ardu de retrouver l'origine.

    Si tu dispose du moyen de l'initialiser sur une valeur correcte, fait le directement, sinon, initialise le à NULL... Mais, quoi qu'il en soit, évite de le laisser initialisé, car, autrement, sa valeur est... strictement tout et n'importe quoi (les "crasses" de la dernière utilisation de la mémoire)... et ca peut être considéré comme une adresse valide

    Prend l'habitude de déclarer constantes les fonctions membres qui n'ont pas vocation à modifier ton objet.

    De cette manière, tu indiques au compilateur ton engagement à ne pas modifier l'objet, et, si tu essaye malgré tout de le faire, tu tombera sur quelqu'un de plus buté que toi qui refusera la compilation (c'est facile, c'est pas cher, et ca peut rapporter gros, en temps économisé au lieu de le passer à se demander "mais pourquoi affiche me vide la pile").

    Enfin, ce n'est peut être qu'un détail, mais je t'ai conseillé plus haut d'utiliser des termes clairs et explicites...

    Cela sous entend de choisir des noms dont le sens est aussi cohérent avec l'usage qu'il en est fait.

    Or, une pile agit, stricto sensu parlant, selon le principe du LIFO (Last In, First Out... dernier entré, premier sorti si tu préfère le français)...

    Si l'on comprend bien que "suivant" te permet de relier l'élément à celui qui a été inséré... avant l'élément en cours, la sémantique voudrais qu'il s'appelle... précédent, vu que c'est, justement, celui d'avant et non celui d'après (ce qui correspond au sens de "suivant")...

    Je t'entend déjà presque penser "mais qu'est-ce qu'il me veut, ce vieux schnock, avec, avec ses conseils à la noix et ses considérations minables", et je ne t'en voudrai certainement pas de le penser...

    Mais, de toutes évidences, tu commence à peine à te frotter à la programmation, et je préfères de loin tenter de te donner directement les bonnes habitudes car tu ne tardera surement pas à te rendre compte que ces conseils "valent de l'or"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut pile en C++
    Merci bien pour votre aide

    j'ai fait en fait un projet qui a 4 fichiers

    1. un fichier.h dans lequel je definnis une structure de type element qui me permet de former ma pile elle est constiuée de deux variables un entier qui prend une valeur à empiler et un pointeur vers le prochain élément de la pile

    2. un fichier .h dans lequel je definis les prototypes de ma classe j'y inclus la structure definie dans le .h preccedent pour definir mes attributs

    3. un fichier .cpp dans lequel j'mplemente mes fonctions

    4. un dernier qui contient mon programme principal

    Ma fonction empiler fait bien son travail mais le probleme c'est afficher

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par patricx Voir le message
    Merci bien pour votre aide

    j'ai fait en fait un projet qui a 4 fichiers

    1. un fichier.h dans lequel je definnis une structure de type element qui me permet de former ma pile elle est constiuée de deux variables un entier qui prend une valeur à empiler et un pointeur vers le prochain élément de la pile

    2. un fichier .h dans lequel je definis les prototypes de ma classe j'y inclus la structure definie dans le .h preccedent pour definir mes attributs

    3. un fichier .cpp dans lequel j'mplemente mes fonctions

    4. un dernier qui contient mon programme principal

    Ma fonction empiler fait bien son travail mais le probleme c'est afficher
    C'est très bien, nous connaissons la structure complète de ton projet et, l'un dans l'autre, elle peut sembler plus ou moins cohérente...

    Mais, dis moi, ton code est-il "top secret"

    Parce que lorsqu'on voit les réticences que tu semble éprouver à nous le montrer, on serait presque enclins à le croire

    Essaye de comprendre que la première règle à suivre, dans ton intérêt, sur le forum est de nous aider à t'aider, si tu veux une aide rapide et efficace.

    Nous sommes là à ne pas demander mieux que de t'aider, mais nous avons l'impression qu'il faut presque te torturer pour t'arracher quelques bribes d'informations sans lesquelles nous aurons le plus grand mal à le faire (t'aider, hein, pas te torturer ) de manière efficace...

    Je te l'ai dit, Madame Irma est en vacances, et personne ici n'a de boulle de crystal en état de marche.

    C'est très gai de jouer au devinettes, mais, il faut comprendre que les gens qui viennent sur ce forum sont tous des bénévoles qui ont une vie en dehors et qui peuvent avoir "autre chose à faire" que d'essayer d'aider quelqu'un presque "malgré lui".

    Si ta fonction Afficher pose problème et qu'elle est écrite tel que tu nous la montre, il n'y a rien à faire, c'est que "la vérité est ailleurs" et que le problème (dont on sait d'ailleurs peu, vu que, visiblement, nous avons déjà donné la solution à ton problème de compilation) trouve son origine... ailleurs.

    Si tu ne nous donnes pas la possibilité de mettre la main sur cet "ailleurs", comment veux tu que nous t'aidions efficacement

    D'autant plus que j'ai l'intime conviction à lire le peu de code que tu nous a présenté et tes interventions que le problème est beaucoup plus profond et tient du problème de conception et de principes incompris.

    Nous pouvons t'aider à évoluer et à comprendre, mais le veux-tu vraiment
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut pile
    Bonsoir et desolé
    il n'est pas du secret
    Je le mets à disposition
    Merci bien

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    C'est mieux... mais tu aurais pu te contenter d'un copier /coller du contenu des fichiers "importants" (pile.h, elt.h, pile.cpp et...main.cpp(il est manquant ) ) directement sur le forum, en prenant soin d'encadrer le code avec les balises [ CODE ] et [ /CODE ] (le bouton # qui se trouve au dessus du formulaire de question /réponse )

    Et, un rapide survol de ton code me fait dire qu'il y a, vraiment, place pour le progres

    Pour la facilité de tous, je vais faire ce copier coller, du moins pour les fichiers dont on dispose, avant de faire mes différentes remarques:
    elt.h original
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //Definition (implementation) d'un élément qui formera la pile
    #ifndef _ELT_H_
    #define _ELT_H_
     
    typedef struct elet 
     
     {
       int valeur;
     
       elet *suivant;
     }
         elt;
     
    #endif
    pile.h original
    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
    //Fichier .h de la classe pile
    #ifndef _PILE_H_
    #define _PILE_H_
    #include "elt.h"
     
    class pile
     
      {            
          elt *un_elt;
     
      //Methodes
           public:
     
      //Methode pour depiler  
     
        elt* empiler(elt *lapile,int a);
     
        //Methode pour lire les valeurs
     
         void lire();
     
        //Methode pour depiler
          elt* depiler(elt *lapile); 
     
       //fonction pour Afficher
     
        void Afficher();
     };
     
     #endif
    pile.cpp original
    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
    #include <iostream>
    #include "elt.h"
    #include "pile.h"
    using namespace std;
     
    //Methode pour Empiler  
     
    elt* pile :: empiler (elt *lapile,int val)
    { elt *p,*elm;
         if(lapile==NULL)
          {lapile=(elt*)malloc(sizeof(elt));
            (*lapile).valeur=val;
             (*lapile).suivant=NULL;
          }
            else
             {  
                 elm=(elt*)malloc(sizeof(elt));
                (*elm).valeur=val;
                (*elm).suivant=lapile;
                 lapile=elm;
           } 
           return lapile ;    
            }
     
    //Methode pour lire les valeurs
     
    void pile::lire()
    {elt *pile;
    int i,n,valeur;
     cout<<"\nDonner la taille de la pile\n";
     cin>>n;
     pile=NULL;
     for(i=1;i<=n;i++) 
     {cout<<"entrer la valeur \t"<<i;
      cin>>valeur;
      pile=pile::empiler(pile,valeur);
     }
     
    }
    ////Methode pour Depiler       
    //elt* pile ::Depiler (elt *lapile)
    // { elt *p;
    //    p=lapile;
    //    lapile=(*lapile).suivant;
    //    free(p);
    // return lapile;   
    //}
     
    //Methode pour Afficher
    void pile::Afficher()
    {
    	pile* p=this;
     
    	while(p!=NULL)
    	{
    	cout<<"\nLa valeur  est \n"<< (*un_elt).valeur;
         un_elt=(*un_elt).suivant;
    	}
    }
    // void pile :: Afficher( elt *lapile)
    // { elt *p;
    //   p=lapile;
    //   while(p!=NULL)
    //   { cout<<"\nLa valeur  est \n"<< (*p).valeur;
    //     p=(*p).suivant;
    //   }
    // }
    Avant d'aller plus loin, si tu dois pisser, sortir le chien, fais le, prend ton paquet de clopes (si tu fumes) à coté de toi, sers toi un café (ou ce que tu veux d'autre), car je prévois de faire encore un post qui entrera dans les annales et qui me vaudra (encore une fois) d'être chambré par mes pairs...

    Pour commencer, je vais faire les remarques d'ordre général que m'inspirent ton code...

    Il faut, en premier lieu, savoir que, contrairement au C, toute définition de type (qu'il s'agisse d'un structure, d'une classe, d'une union ou d'une énumération) rend automatiquement le type disponible à l'utilisation.

    Il ne sert donc à rien de rajouter un typedef lorsque tu définit une strucutre.
    Un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct MaStructure
    {
        /*blabla */
        /* tu peux même utiliser directement MaStructure en interne */
        MaStructure * truc;
    };
    suffit.

    De plus, il faut savoir qu'il n'y a que très peu de différence entre les classes et les structures en C++...

    Elles tiennent principalement à l'accessibilité qui est appliquée par défaut à leur contenu (cf l'entrée de la FAQ qui en parle)

    Pour travailler "entièrement" en orienté objet, nous pourrions donc envisager de créer non pas une structure de type el(e)t mais... carrément une classe dont je parlerai en temps utiles.

    Ensuite, je voudrais attirer ton attention sur deux points que j'ai oublié de citer dans les conseils pour garder un code lisible et que ton code met en évidence:

    Tous deux concernent les commentaires...

    Les commentaires sont très utiles, pour ne pas dire indispensables dans certains cas.

    Mais il vaut mieux se passer de commentaire que d'en avoir de mauvais.

    Un "bon" commentaire sera un commentaire qui apporte une information qu'une lecture rapide du code ne met peut être pas en évidence.

    Il ne faut pas vraiment sortir de Math Sup pour comprendre qu'une fonction nommée explicitement empiler va servir à ... empiler des objets... On se doute que le but de la fonction n'est pas de partir à la chasse au papillons

    De même un commentaire proche de (je te rassure, il n'y en a pas dans ton code )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int i;
    i++; // incrémente i
    n'a en définitive aucun intérêt: il n'appporte aucune indication que le code ne donne pas.

    Par contre, si l'explication vise à expliquer pourquoi on décide d'incrémenter i, le commentaire peut prendre tout son sens (car l'incrémentation peut sembler aller "à contre courent" de la logique de la fonction)

    Le deuxième conseil que je veux rajouter découle directement du premier:

    Ne laisse pas du code "périmé" et commenté dans ton code.

    Il peut arriver que l'on souhaite "désactiver" une portion de code le temps d'effectuer un test, et il est donc "envisageable" de commenter cette portion le temps de faire le test en question.

    Mais ce code ne doit pas rester si son inutilité est avérée et que son retrait ne provoque aucun problème: Soit la portion désactivée est nécessaire, et il faut la "dé-commenter", soit elle n'est pas nécessaire, et il faut la supprimer:

    La présence de ce code désactivé complique en effet fortement la relecture, que ce soit en obligeant le lecteur à jouer avec les ascenseurs pour accéder à la suite ou, pire encore (on ne lit pas forcément un code avec un outil disposant de la coloration syntaxique et certains ont même ce genre d'outils en horreur) ne pas être interprété comme tel par le lecteur et l'induire en erreur sur ce qui est *réellement* fait.

    Je constate, en outre, que tu utilise la fonction C malloc pour tes allocation dynamiques...

    Ce n'est pas à proprement une faute dans le sens où cette fonction existe aussi en C++, mais c'est néanmoins une erreur dans le sens où, à l'instar de nombreuses autres choses issues du C, C++ propose une alternative beaucoup plus facile et sécurisante à utiliser: new, dans le cas présent.

    En effet, alors que malloc se contente de renvoyer un pointeur vers la mémoire allouée dynamiquement (ou NULL si l'allocation a échoué), new permet d'appeler directement le constructeur de la classe, et donc d'obtenir directement un objet correctement initialisé selon les règles que nous avons décidé (nous approchons du concept RAII (Ressource Acquizition Is Initialisation, L'acquisition de ressources vaut initialisation si tu préfère en français) ), mais, en plus, mais, en plus, il ne renverra le pointeur que si l'allocation a bel et bien eu lieu (il lancera une exception de type bad_alloc si elle a échoué).

    Et, cerise sur le gâteau, la syntaxe est autrement plus simple:

    En effet, là où tu dois écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type * ptr = (Type*) malloc(sizeof(Type));
    avec malloc, tu peux te contenter d'un simple
    voire, si tu dois passer des arguments pour contruire ton objet d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type *ptr= new Type(/* les arguments nécessaires*/)
    Evidemment, si on "renonce" à malloc au profit de new, il faut renoncer à free au profit de delete (il ne faut en aucun cas appeler free sur un pointeur alloué par new ni appeler delete sur un pointeur alloué par malloc).

    Et, bien sur, delete présente lui aussi un avantage certain par rapport à free: il appelle automatiquement le destructeur de l'objet avant de libérer la mémoire allouée, ce qui provoque la libération correcte et en profondeur des ressources allouées à l'objet

    Pour en terminer avec les généralités, je voudrais, après avoir insisté une fois de plus sur l'importance de respecter une politique d'indentation stricte et cohérente, te parler de la manière dont tu accède aux éléments de tes pointeurs.

    En effet, tu y accède systématiquement sous la forme de
    qui, bien que n'étant pas tout à fait fausse me semble être une habitude par laquelle tu te fait du mal inutilement...

    En effet, il existe une syntaxe particulière pour accéder au contenu d'un pointeur: la fleche " -> "...

    Dés lors, pourquoi se faire du mal à vouloir prendre "ce qui est pointé par" ton pointeur avant d'essayer d'accéder à son contenu

    D'autant plus que, pour l'instant, tu as de la chance : tu tente tout de suite d'accéder... au contenu du pointeur, mais quid si tu essayais d'accéder au contenu d'un pointeur qui est lui-même contenu dans un autre objet vers lequel tu dispose d'un pointeur

    Ne crois tu pas qu'il est presque plus rapide d'utiliser la fleche sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lePointeur->ptr->truc/*...*/;
    plutôt que ta méthode, qui se traduirait par un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*lePointeur).(*ptr).truc/*...*/


    Et ce serait encore pire si tu essayais d'accéder au contenu d'un pointeur qui est lui même contenu dans un pointeur renvoyé par la fonction membre d'un objet dont tu ne dispose que sous la forme d'un pointeur

    De plus, bien que n'étant pas erronée, ta méthode présente un inconvénient majeur : elle va à l'encontre des pratiques habituelles de la communauté en générale.

    De ce fait, tu t'éloigne de la première qualité d'un code qui est d'être facilement lisible par "le plus grand nombre"...

    Bien sur, tout programmeur digne de ce nom comprendra ton code, mais disons que, tu risque de voir des points d'interrogation voler autour de sa tête le temps qu'il "percute" sur ton habitude peu orthodoxe...

    Ceci étant dit, je voudrais pointer du doigt la logique assez particulière que tu mets en oeuvre dans ta fonction empiler (hé oui, tu t'es un peu avancé en criant bien haut que la fonction empiler fonctionnait correctement)...

    A vrai dire, j'ai un peu de mal à comprendre pourquoi tu passe un pointeur sur ce qui, de toutes évidences, est destiné à devenir... le dernier élément emplié, alors que ta pile dispose d'un tel pointeur sous la forme de ... un_elt, et, surtout, pourquoi tu travaille essentiellement avec le pointeur passé en argument et non avec... un_elt... qui n'est jamais utilisé dans la fonction empiler (et dont je doute qu'il le soit dans la fonction depiler, mais, comme tu as eu l'extrême amabilité de nous en cacher le code...)

    Si c'est pour garder artificiellement le pointeur représentant le haut de la pile en dehors de la pile, à quoi peut donc bien servir ce membre un_elt , et, par voie de conséquence, pourquoi créer une classe pile alors que tout ce qui semble t'intéresser pourrait prendre la forme de fonctions libres

    Finalement, j'ai changé d'avis...

    Au départ, j'avais en tête de te présenter point par point une manière correcte et efficace de mettre ta pile au point, mais, je me rend compte que mon intervention prend déjà l'allure d'un véritable roman (et que je suis déjà sur de me faire chambrer)...

    De plus, je me dis qu'il te faudra un certain temps pour assimiler les différentes remarques que j'ai faite et pour arriver à les appliquer de manière cohérente dans ton code.

    Enfin, je me dis que ce serait peut être un très mauvais service à te rendre que de *trop* te mâcher la tâche (sans oublier que ce serait récompenser un peu facilement ton manque de collaboration).

    Je vais donc te laisser réfléchir un peu à tout cela, et j'attends de tes nouvelles pour voir comment tu aura pris ces remarques en compte, voire, te donner l'occasion de poser des questions supplémentaires sur celles-ci, avant de risquer de te larguer complètement avec la suite des explications...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut code
    bonsoir et Six miliards de merci pour les explications et les remarques je vais me baser sur tout ça et essayer de refaire un code plus clair
    Encore Merci

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut pile
    Bonsoir j'ai tant bien que mal ce qui m'a été fourni comme aide
    j'ai ce code joint

    et mon problème est toujours l'affichage

    et aussi l'allocation de lapile dans la methode empiler

    Merci bien

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    La première chose que tu dois absolument comprendre, bien que cela nous oblige à voir les choses quelque peu à l'envers (mais peut être est-ce que cela t'aidera à mieux cerner ce que l'on essaye de t'expliquer), c'est qu'une classe c'est une structure de données "à la C" avec un peut plus: le fait de pouvoir placer des fonctions dans la structure qui peuvent accéder "en toute liberté" aux différents éléments de cette structure.

    Comme tu a placé un pointeur de type structure (anciennement elt) dans ta classe pîle, tu peux (et j'irais volontiers jusqu'à dire "tu dois") utiliser ce pointeur pour gérer les différents éléments qu'elle contient:

    Tu n'a strictement "rien à foutre" de garder un pointeur vers le dernier élément de la pile en dehors de celle-ci:

    Tu crée ta pile et tu la manipule à coup de empiler, depiler, lire ou afficher, et, en interne, chacune de ces fonction va utiliser le pointeur de type structure (anciennement de type elt) nommé element (anciennement nommé un_elt) pour faire ce que l'on attend d'elle.

    Il ne faut passer ni un pointeur vers structure (anciennement elt) ni un pointeur vers pile à tes fonctions: elles ont tout ce qui leur faut (à part la valeur à assigner à chaque élément).

    Relis peut être ma troisième intervention sur cette discussion, et particulièrement la partie qui commence par
    Or, et c'est là toute la "beauté"...
    et qui s'arrête juste avant
    La seule chose à laquelle tu doive être attentif,...
    et dis nous si tu comprend déjà ce que j'ai voulu dire par là...

    J'ai en effet la réelle impression que tu ne comprend déjà pas ce qu'est le paradigme orienté objet... Or, tant que tu n'auras pas cette compréhension, nous pourrions pisser dans un violon, nous arriverions au même résultat: nous ferions beaucoup de vent pour rien
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut
    Bonjour
    Je suis désolé de faire trainer un sujet mais là je suis tout perdu
    Est ce que ça veut dire qu'il me faut éliminer ma structure et créer directement deux attributs (int val, et un pointeur de type pile) dans ma classe pile?
    ensuite à ma methode empiler je passe juste la valeur??

    ben là mon problème est qu'elle retourne et comment gerer tout ça

    Désolé encore et Merci pour votre patience

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    non, le "découpage" des responsabilité est bon, et tu dois garder ta structure "structure" (anciennement elt) et ta classe pile.

    Mais tu déclares un membre "element" (anciennement un_elt) dans ta pile.

    Les différentes fonctions de pile ont naturellement accès à ce membre et doivent l'utiliser dans leur gestion des différents éléments contenu par la pile.

    Que ce soit dans empiler, depiler, afficher ou lire, tu peux, n'importe quand écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void pile::afficher() // tu remarque que je ne transmet aucune info
                    // complémentaire
    {
        element->valeur;
        /*voire, si tu veux accéder à l'élément qui suit celui en cours*/
        element->next;
    }
    Ce membre fait partie de ce que l' on appelle les "détails d'implémentation".

    C'est à dire que la personne qui utilise le type pile ne doit, à l'extrême limite, même pas savoir qu'il existe un type nommé structure pour être en mesure de l'utiliser.

    Or, comment voudrais tu arriver à transmettre en paramètre quelque chose... dont tu ignore (à l'extrême limite) jusqu'à l'existence

    Ceci dit, même si ce n'est qu'un détail, le choix des différents noms laisse toujours à désirer:

    Ta structure nommé structure (anciennement elt) devrait s'appeler, Element, par exemple, le nom du membre de la pile pourrait être last, car il s'agit d'un pointeur vers... le dernier élément de la pile

    Pour te mettre sur la voie, voici plus ou moins (en respectant ce que j'ai dit jusqu'à présent et en me basant sur ce que tu as fait) comment les choses devrait se présenter:

    Le type pour représenter un élément (actuellement structure, anciennement elt)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Element
    {
        int valeur;
        Element * precedent;
    };
    Le type pour représenter la pile
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Pile
    {
        public: 
            ~Pile(); //à ne pas oublier... pour la destruction correcte de la pile
            bool empiler(int val);
            void depiler();
            void lire();
            void afficher();
    };
    Les fonctions membres de pile
    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
    Pile::~Pile()
    {
        // à toi de jouer
    }
    bool Pile::empiler(int val)
    {
        // à toi de jouer
    }
    void Pile::depiler()
    {
        // à toi de jouer
    }
    void Pile::lire()
    {
        // à toi de jouer
    }
    void Pile::afficher()
    {
        // à toi de jouer
    }
    Tu ne dois rien changer à la signature de ces fonctions, mais je te laisse le soin d'écrire le contenu des fonctions.

    N'oublie pas que chacune de ces fonctions connait tout à fait naturellement le pointeur de type Element (anciennement structure et elt) nommé "last" (anciennement element et un_elt) et que ta logique doit se baser sur... cet élément particulier

    Pour te permettre de faire le test, voici la fonction principale que tu dois utiliser:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        Pile p;
        p.lire();
        P.afficher();
        return 0;
    }
    Nous sommes encore fort loin d'avoir une pile "idéale", mais je veux m'assurer que tu aura compris jusque là, et le code que tu me présentera pour les différentes fonctions me permettra de me faire une idée.

    NOTA: n'oublie pas qu'il ne sert pas à grand chose de placer systématiquement les fichier dans une archives et de les proposer en pièce jointe...

    tu dispose, au dessus du formulaire, d'un bouton # qui place des balises [ CODE ] et [ /CODE ](sans les espaces) dans le formulaire de réponse

    Copie ton code (ou fait un copier / coller, cela fonctionne aussi) entre ces balises. Nous pourrons lire ton code à l'affichage de ta réponse, en disposant de la coloration syntaxique et l'indentation sera respectée, sans devoir télécharger et extraire une archive
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut pile
    Merci bien encore pour l'aide

    la methode empiler ( bool empiler(int val) je comprend pas comment ça va retourner un booléen

    la méthode depiler comment ça retournera rien
    Dans ma logique empiler sera appelée dans lire comme dans mes codes preccedents

  18. #18
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par patricx Voir le message
    Merci bien encore pour l'aide

    la methode empiler ( bool empiler(int val) je comprend pas comment ça va retourner un booléen

    la méthode depiler comment ça retournera rien
    Dans ma logique empiler sera appelée dans lire comme dans mes codes preccedents
    En fait, j'ai mis un booléen de manière à pouvoir vérifier si l'empilage a bien été effectué...

    Mais tu peux effectivement remplacer le booléen de retour par void, à condition que tu utilise new (qui lance une exception de type bad_alloc si l'allocation de mémoire échoue) et non malloc
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 152
    Points : 42
    Points
    42
    Par défaut empiler
    désolé mais Sincèrement je ne vois pas trop comment ecrire empiler sans lui passer ma structure de mme que depiler

  20. #20
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par patricx Voir le message
    désolé mais Sincèrement je ne vois pas trop comment ecrire empiler sans lui passer ma structure de mme que depiler
    Mais tu n'a pas à passer la structure, car les fonctions membres d'une classe ou d'une structure font partie intégrante de la classe ou de la structure.

    Hormis le fait que ce sont des fonctions, ce sont des membres de la classe ou de la structure exactement au même titre que n'importe quelle variable que tu voudrais mettre dans ta structure...

    Le "petit plus" que l'on observe du fait que ce sont des fonctions, c'est qu'elle connaissent le contenu intégral de la structure, et qu'elle dispose même d'un pointeur (nommé this) sur l'objet en cours.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Afficher la pile d'appel Tcl depuis une fonction C
    Par grismauve dans le forum Tcl/Tk
    Réponses: 0
    Dernier message: 19/09/2009, 10h22
  2. Réponses: 14
    Dernier message: 20/04/2007, 09h09
  3. Afficher une image sans passer par les textures
    Par Black_Daimond dans le forum DirectX
    Réponses: 3
    Dernier message: 09/05/2003, 19h13
  4. Afficher une buffer de pixel avec Direct3D
    Par Black_Daimond dans le forum DirectX
    Réponses: 4
    Dernier message: 27/12/2002, 22h18
  5. Copier et afficher une copie d'ecran
    Par Bobx dans le forum Langage
    Réponses: 6
    Dernier message: 02/08/2002, 22h20

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