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 :

Affichage de listes de différents types


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 116
    Points : 45
    Points
    45
    Par défaut Affichage de listes de différents types
    J'utilise cette fonction pour afficher le contenu d'une liste:

    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
     
    short print(list<ELEM_D> &l)
    {
        list<ELEM_D>::iterator i = l.begin();
        cout << "----------------\n";
        if (l.size() == 0)
        {
            cout << "Liste vide!!!\n";
            cout << "----------------\n";
            return 1;                                  // La liste est vide !!
        }
        while (i != l.end())
        {
            i->affiche();
            ++i;
            cout << "----------------\n";
        }
        cout << endl;
    return 0;                                      // Tout s'est bien passé
    };
    C'est très bien mais j'aimerais utiliser la même fonction pour commander l'affichage de liste ELEM_C, ELEM_D, double etc...

    Pour l'instant je surdéfini mais ça produit 3 fois le même code excepté le paramètre et l'itérateur.
    Je trouve ça vraiment bête et j'aimerais rationaliser. Possible?

    D'avance merci pour vos lumières !

  2. #2
    Membre averti Avatar de xxiemeciel
    Inscrit en
    Juin 2005
    Messages
    371
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 371
    Points : 352
    Points
    352
    Par défaut
    Salut,

    Tu peux faire de ta fonction print une fonction template.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<class ELEM>
    short print(list<ELEM> &l)
    {
     ///etc...
    }
     
    ensuite tu appelles print<ELEM_S> ou print<ELEM_D> etc ...
    XXiemeciel

  3. #3
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 116
    Points : 45
    Points
    45
    Par défaut
    En voilà une réponse quelle est rapide!!

    Ha ça je vais plancher car j'ai pas encore du employer ces bestioles-là.
    Et ça a le mérite de me faire tout de suite comprendre à quoi elles servent...

    Un grand merci !!

  4. #4
    Membre averti Avatar de xxiemeciel
    Inscrit en
    Juin 2005
    Messages
    371
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 371
    Points : 352
    Points
    352
    Par défaut
    Je pense si tu cherches un peu tu trouveras des tutoriels sur les templates sur developpez.com.

    XXiemeciel

  5. #5
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 116
    Points : 45
    Points
    45
    Par défaut
    OK j'ai compris. C'est assez simple pour un cas comme le mien.
    Evidemment pour une liste de double j'ai un problème puisque
    n'est plus correct puisque le compilateur attend une structure à gauche de ->. Or je n'avais pas fait de fonction affiche() pour le type double car je ne sais pas comment faire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class double
    {
       void affiche();
    };
     
    void double::affiche()
    {
      cout << *i << " ";
    return;
    };
    Me revoie un paquet d'erreurs...

  6. #6
    Membre averti Avatar de xxiemeciel
    Inscrit en
    Juin 2005
    Messages
    371
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 371
    Points : 352
    Points
    352
    Par défaut
    tu peux creer un template specifique pour le cas double

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template<class ELEM>
    short print(list<ELEM> &l)
    {
     ///etc...
    } 
     
    template<class>
    short print<double>(list<double> &l)
    {
     //code specifique pour double
    }
    je suis pas sur a 100% de la syntaxe mais ca peut se faire. Ensuite les appel se font pareil :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    print<ELEM_D>(...);
    print<double>(...);
    etc...
    XXiemeciel

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Ou définir l'opérateur d'injection dans les flux (>>) pour tes objets...

  8. #8
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 116
    Points : 45
    Points
    45
    Par défaut
    Ca marche super avec les templates.

    Je me suis rendu compte mes 2 classes (-> statistiques: donc une classe pour le type continu et une pour le type discret. Les instances de ces classes étant chainées (merci la STL)) ont beaucoupl plus en commun que ke ne le pensais et j'ai donc crée un classe mère que je dérive.
    Ca fait merveille en combinant ça avec les templates.

    Maintenant j'ai eu un petit soucis que j'ai réglé mais "à la bourrin".
    J'ai une fonction chargée de calculer effectif x valeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    short geteffxval(list<ELEM_C> & _liste_d, double &_sommeeffxval){
        list<ELEM_C>::iterator i = _liste_d.begin();
        while (i!= _liste_d.end())
            {
            i->puteffxval(i->geteff()*i->getcentre());
            _sommeeffxval=_sommeeffxval+i->geteff()*i->getcentre();
            i++;
            }
    return 0;};
    Je pourrais surdéfinir (je l'ai fait ça tourne très bien) et ajouter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    short geteffxval(list<ELEM_D> & _liste_d, double &_sommeeffxval){
        list<ELEM_D>::iterator i = _liste_d.begin();
        while (i!= _liste_d.end())
            {
            i->puteffxval(i->geteff()*i->getval());
            _sommeeffxval=_sommeeffxval+i->geteff()*i->getval();
            i++;
            }
    return 0;};
    Les différences sont que la première prend une list<ELEM_C> et appelle getcentre() alors que la seconde prend une liste <ELEM_D> et appelle getval().

    Mais pourquoi pas une template. Cela résoudrait le problème ELEM_C/ELEM_D. Reste le problème de l'appel à getval() ou getcentre. Je pourrais rajouter un paramètre (un bool c'est le plus facile) afin de savoir que faire à l'intérieur de la fonction.

    Problème réglé. Sauf que... le compilateur m'indique que getval n'est pas défini pour ELEM_C et que getcentre ne l'est pas pour ELEM_D ce qui est normal mais qui m'embête beaucoup

    J'ai alors créé des fonction "bidon" sachant que de toute façon elles ne seront pas exécutées. Mais je trouve pas très très bien et j'aurais aimé savoir s'il était possible de faire ça plus proprement.
    Voici le code de la fonction version template:
    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
    template <typename T> short geteffxval(list<T> & _liste_d, double &_sommeeffxval, bool _discret){
     
        list<T>::iterator i = _liste_d.begin();
        while (i!= _liste_d.end())
            {
            if (_discret)
              {
                i->puteffxval(i->geteff()*i->getval());
                _sommeeffxval=_sommeeffxval+i->geteff()*i->getval();
              }
            else
              {
                i->puteffxval(i->geteff()*i->getcentre());
                _sommeeffxval=_sommeeffxval+i->geteff()*i->getcentre();
              }
            i++;
            }
    return 0;};
    J'espère que ce n'est pas trop nébuleux je peux mettre l'ensemble de mon code dispo si cela peut aider...

  9. #9
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par thibouille
    Maintenant j'ai eu un petit soucis que j'ai réglé mais
    "à la bourrin". J'ai une fonction chargée de calculer effectif x valeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    short geteffxval(list<ELEM_C> & _liste_d, double &_sommeeffxval){
        list<ELEM_C>::iterator i = _liste_d.begin();
        while (i!= _liste_d.end())
            {
            i->puteffxval(i->geteff()*i->getcentre());
            _sommeeffxval=_sommeeffxval+i->geteff()*i->getcentre();
            i++;
            }
    return 0;};
    Quelques petites remarques sur le style:
    • les identificateurs commençant par un underscore et ceux qui en comportent deux de suite sont réservés pour l'implémentation (les règles sont un peu plus complexes que ça, mais retenir celle-ci est facile et ne génère aucun problème). Il vaut mieux les éviter parce que d'une implémentation à l'autre, ceux qui sont réellement utilisés varient;
    • il est courant de réserver les identificateurs tout en capitale pour le préprocesseur;
    • j'aime pas trop le mélange de l'anglais et du français, et encore moins une syntaxe anglais avec des mots français (effectif x valeur);
    • tu ne modifies pas la liste, pourquoi ce paramètre n'est-il pas const?
    • je n'aime pas du tout les méthodes de nommage qui n'offrent aucune indication sur la séparation des mots dans les noms.

    Je pourrais surdéfinir (je l'ai fait ça tourne très bien) et ajouter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    short geteffxval(list<ELEM_D> & _liste_d, double &_sommeeffxval){
        list<ELEM_D>::iterator i = _liste_d.begin();
        while (i!= _liste_d.end())
            {
            i->puteffxval(i->geteff()*i->getval());
            _sommeeffxval=_sommeeffxval+i->geteff()*i->getval();
            i++;
            }
    return 0;};
    Les différences sont que la première prend une list<ELEM_C> et appelle getcentre() alors que la seconde prend une liste <ELEM_D> et appelle getval().

    Mais pourquoi pas une template?
    Comme paramètre template, tu peux avoir des pointeurs sur fonction membre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <typename Ty, double(Ty::* func)()>
    short geteffxval(list<Ty>& _liste_d, double &_sommeeffxval){
        list<Ty>::iterator i = _liste_d.begin();
        while (i != _liste_d.end())
        {
            i->puteffxval(i->geteff() * ((*)i.*func)());
            _sommeeffxval = _sommeeffxval + i->geteff() * ((*i).*func)();
            i++;
        }
        return 0;
    };
    à appeler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    geteffxval<ELEM_D, &ELEM_D::getval>(liste, somme);
    C'est pas très pratique à appeler. Donc on peut utiliser la technique des traits pour donner une valeur par défaut convenable.

    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
    template <typename Ty>struct EffXValTrait{};
    template <> struct EffXValTrait<ELEM_D> {
       static double (ELEM_D::*func)();
    }
    double (ELEM_D::* EffXValTrait<ELEM_D>::func)()
     = &ELEM_D::getval;
    template <> struct EffXValTrait<ELEM_C> {
       static double (ELEM_C::*func)() = &ELEM_C::getcentre;
    }
    double (ELEM_C::* EffXValTrait<ELEM_C>::func)()
     = &ELEM_C::getval;
     
    template <typename Ty>
    short geteffxval(list<Ty>& _liste_d, double &_sommeeffxval){
        list<Ty>::iterator i = _liste_d.begin();
        while (i != _liste_d.end())
        {
            i->puteffxval(i->geteff() * ((*)i.*(EffXValTraits<Ty>::func))());
            _sommeeffxval = _sommeeffxval + i->geteff() 
                            * ((*i).*(EffXValTraits<Ty>::func))();
            i++;
        }
        return 0;
    };
    qu'on appelle par Généralement, on utilise un paramètre template avec une valeur par défaut pour les traits, mais de tels paramètres ne sont pas autorisés pour les fonctions. Un exemple qui compile si le copier/coller ne m'a pas joué un tour que je n'ai pas vu (il m'en a joué que j'ai remarqués):
    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
    #include <iostream>
    #include <list>
    #include <assert.h>
     
    class Continuous
    {
    public:
      double getCenter() const { return 0; }
    };
     
    class Discrete
    {
    public:
      double getValue() const { return 0; }
    };
     
    template <typename Ty, double (Ty::*func)() const>
    double mean(std::list<Ty> const& l)
    {
      double sum;
      assert(l.size() != 0);
      typedef typename std::list<Ty>::const_iterator Iter;
      for (Iter i = l.begin(),
             e = l.end();
           i != e;
           ++i)
      {
        sum += ((*i).*func)();
      }
      return sum/l.size();
    }
     
    template <typename Ty> struct MeanTraits {};
    template <> struct MeanTraits<Continuous>
    {
      static double (Continuous::*func)() const;
    };
    double (Continuous::* MeanTraits<Continuous>::func)() const
      = &Continuous::getCenter;
     
    template <> struct MeanTraits<Discrete>
    {
      static double (Discrete::*func)() const;
    };
    double (Discrete::* MeanTraits<Discrete>::func)() const
      = &Discrete::getValue;
     
    template <typename Ty>
    double meanWithTraits(std::list<Ty> const& l)
    {
      double sum;
      assert(l.size() != 0);
      typedef typename std::list<Ty>::const_iterator Iter;
      for (Iter i = l.begin(),
             e = l.end();
           i != e;
           ++i)
      {
        sum += ((*i).*(MeanTraits<Ty>::func))();
      }
      return sum/l.size();
    }
     
    int main()
    {
      std::list<Continuous> lc;
      std::list<Discrete> ld;
      std::cout << mean<Continuous, &Continuous::getCenter>(lc)
                << mean<Discrete, &Discrete::getValue>(ld)
                << meanWithTraits(lc)
                << meanWithTraits(ld);
    }

  10. #10
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    116
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 116
    Points : 45
    Points
    45
    Par défaut
    Un grand merci pour cette aide très précieuse et tes remarques judicieuses (dont je suis conscient mais je suis fort sous pression (examen) et je n'ai donc pas eu le temps dem'en occuper).

    Maintenant que le plus dur est fait, je vais de ce pas remédier à cela.

    Merci encore !! 8)

Discussions similaires

  1. Réponses: 6
    Dernier message: 30/03/2015, 11h41
  2. [SP-2010] problème d'affichage de liste de type de contenu externe
    Par bého32 dans le forum SharePoint
    Réponses: 10
    Dernier message: 06/07/2012, 22h44
  3. Combiner différents types dans une liste chaînée en c
    Par roka1988 dans le forum Débuter
    Réponses: 2
    Dernier message: 21/03/2012, 10h51
  4. Affichage d'un parametre de type List
    Par Spiritkill dans le forum Jasper
    Réponses: 7
    Dernier message: 08/08/2011, 08h11
  5. [MySQL] Affichage en liste de type et de leurs sous-types
    Par Mitaka dans le forum PHP & Base de données
    Réponses: 12
    Dernier message: 09/11/2005, 14h33

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