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 :

accéder aux éléments d'un tableau dynamique ( pointeurs )


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2019
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2019
    Messages : 1
    Points : 2
    Points
    2
    Par défaut accéder aux éléments d'un tableau dynamique ( pointeurs )
    Bonjour , j'ai un tableau dynamique des pointeurs d'une classe ( Exemplaire ) , cette derniére a un attribut : Oeuvre , je souhaite vérifier si ce dernier est egale à un argument , comme il est indiqué dans le code :

    #la_classe_exemplaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Exemplaire {
    private:
        Oeuvre oeuvre ;
    public : 
    Oeuvre getOeuvre()
        {
            return oeuvre;
        }
    };
    #la_déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    private:
     vector<Exemplaire*> exemplaire;
    #la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int compter_exemplaires(Oeuvre &o){
        int j=0;
        //Exemplaire* ex=new Exemplaire(o);
    for (int i=0;i<exemplaire.size();i++){if(exemplaire[i].getOeuvre()==o){j=j+1;}
    return j;}}
    j'ai essayé ça aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (auto & Exemplaire:exemplaire){if(exemplaire->getOeuvre()==o){j=j+1;}

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

    Informations professionnelles :
    Activité : aucun

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

    Si tu travailles avec des pointeurs, tu dois utiliser la flêche -> pour accéder à la partie de l'objet pointé, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     for(size_t i 0; i< exemplaire.size(); ++i){ // std::vector<T>.size() renvoie une valeur de type size_t, 
                                                 // autant utiliser ce type pour éviter les problèmes
        exemplaire[i]->getOeuvre();
    }
    /* depuis C++11, on dispose des boucles pour "range based", qui sont plus faciles 
     * ainsi que du mot clé auto qui simplifie énormément les choses
     */
    for(auto * it : exemplaire){
        it->getOeuvre();
    }
    NOTA: Si tu utilises l'allocation dynamique pour créer les objets que tu places dans ton tableau, tu devrais utiliser les pointeurs intelligents (std::unique_ptr, par exemple), car ton programme là, il est fondamentalement buggé : si une allocation mémoire échoue (et il y en aura beaucoup si tu travaille avec un std::vector et avec des pointeurs), tu vas te retrouver avec un maximum de fuites mémoires

    Je verrais bien quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<std::unique_ptr<Exemplaire>> exemplaire;
    avec quelques modifications à effectuer,
    - pour ajouter un exemplaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto temp = std::make_unique<Exemplaire>(/* paramètres requis*/);
    exemplaire.push_back(std::move(temp));
    - pour accéder au contenu de l'exemplaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for auto const & it : exemplaire){
        it.get()->getOeuvre()/* ... */;
    }
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Au passage, quelques remarques sur ton code en général:

    1- Il existe une loi en programmation: la loi dite "de Déméter", qui nous dit en substance que
    Citation Envoyé par loi de Déméter
    Si un objet de type A (ta classe Exemplaire, dans le cas présent) utilise en interne un objet de type B(ta classe Oeuvre, dans le cas présent), l'utilisateur d'un objet de type A (comprend: d'un exemplaire quelconque) ne devrait pas avoir à connaître le type B (comprend: l'oeuvre) pour manipuler son objet de type A (comprends: l'exemplaire)
    Bien sur, il en va de même pour ta classe Oeuvre, qui utilise sans doute en interne un objet de type Auteur .

    Si bien que, dans l'idéal, tu devrais modifier tes classes Auteur, Oeuvre et Exemplaire de la manière suivante

    La classe Auteur ne change sans doute pas énormément:
    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
    class Auteur{
    public:
        Auteur(std::string const & nom, std::string const & langue):
            nom_{nom}, langue_{langue}{
        }
        /* on veut connaitre le nom de l'auteur */
        std::string const & nom() const{
            return nom_;
        }
        /* on veut savoir dans quelle langue il écrit ses oeuvres */
        std::string const & langue() const{
            return langue_;
        }
    private:
        std::string nom_;
        std::string langue_;
    };
    la classe Oeuvre prendrait la forme 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
    16
    17
    18
    19
    20
    21
    22
    23
    class Oeuvre{
    public:
        Oeuvre(std::string const & titre, Auteur const & auteur):
            titre_{titre},auteur_{auteur}{
        }
        /* on veut connaire le titre original (dans la langue utilisée par l'auteur)
         * de l'oeuvre
         */
        std::string const & titreOriginal() const{
            return titre_;
        }
        /* on veut savoir qui a écrit l'oeuvre */
        std::string const & ecritPar() const{
            return auteur_.nom();
        }
        /* on veut savoir la langue dans laquelle il a été écrit à l'origine */
        std::string const & langueOriginale() const{
            return auteur_.langue();
        }
    private:
        std::string titre_;
        Auteur auteur_;
    };
    et enfin,ta classe Exemplaire prendrait la forme 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
    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
    class Exemplaire{
    public:
        /* Parce que l'on a peut-être affaire à une traduction ... ou non */
        Exemplaire(Oeuvre const & oeuvre, std::string const & titre = "", std::string const & langue=""):
            oeuvre_{oeuvre}, titre_{titre}, langue_{langue}{
        }
        /* On veut savoir qui a écrit l'oeuvre */
        std::string const & ecritPar() const{
            return oeuvre_.ecritPar();
        }
        /* on veut connaitre le titre original  de l'oeuvre*/
        std::string const & titreOriginal() const{
            return oeuvre_.titreOriginal();
        }
        /* on veut connaitre le titre de l'exemplaire actuel:
         * - soit, c'est le titre original de l'oeuvre, 
         * - soit, c'est la traduction (dans une langue donnée) de ce titre
         */
        std::string const & titre() const{
            if(titre_.empty())
                return titreOriginal();
            return titre_;
        }
        /* on veut connaire la langue original de l'oeuvre */
        std::string const & langueOriginale() const{
            return oeuvre_.langueOriginale();
        }
        /* on veut connaitre la langue spécifique de l'exemplaire 
         * - Soit c'est la langue originale de l'eouvre
         * - soit c'est la langue dans laquelle l'oeuvre a été traduit
         */
        std::string const & langue() const{
            if(langue_.empty())
                return langueOriginale();
             return langue_;
        }
    private: 
        Oeuvre oeuvre_;
        std::string titre_;
        std::string langue_;
    };
    De cette manière, ta fonction compterExempaire pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int compter_exemplaires(std::string const & titre,std::string const & ecritPar){
        int compte{0};
        for(auto * it : exemplaires){
            if(it->titreOriginal() == titre &&
               it->ecritPar() == ecritPar){
                ++compte;
             }
        }
        return compte;
    }
    Et nous pourrions même améliorer les chose de manière à savoir le nombre d'exemplaires de l'oeuvre qui sont en VO et celui de ceux qui sont une traduction en créant une petite structure proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct Decompte{
       size_t versionOriginale{0};
       size_t traduction{0};
    };
    nous n'aurions "qu'à" modifier notre fonction compter_exemplaires pour lui donner une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int compter_exemplaires(std::string const & titre,std::string const & ecritPar){
        Decompte compte;
        for(auto * it : exemplaires){
            if(it->titreOriginal() == titre &&
               it->ecritPar() == ecritPar){
                if(it->titre() == titre)
                    ++compte.versionOriginale;
                else
                    ++compte.traduction;
             }
        }
        return compte;
    }
    le total des exemplaire (VO et traduction confondues) pouvant être obtenu en additionnant les deux valeurs récupérées

    2- L'idéal, quand tu as affaire à des éléments complexes (comme les classes Auteur, Oeuvre et Exemplaire) est -- autant que faire se peut -- d'en éviter la copie. Tu n'imagine pas la perte de performances que peut entrainer une copie inutile

    C'est d'autant plus vrai quand les objets que tu manipules sont uniques. Or, les auteurs, les oeuvres qu'ils ont écrits et les exemplaires de ces oeuvres sont, justement absolument unique:
    • Même si Henry Vernes est un auteur qui existe (il a écrit les Bob Morane, entre autres), il n'a absolument rien à voir avec Jules Vernes (20 000 lieues sous les mers, et autres)
    • Même si deux oeuvres écrites par des auteurs différents peuvent porter le même titre (j'ai croisé quelques exemples ) chaque oeuvre n'a été écrite que ... par un (ou plusieurs) auteur(s) bien spécifique(s)
    • Rien n'empêche que tu aies un exemplaire de 20 000 lieues sous les mers en main et ... que j'en aie un autre en main au même moment


    Le meilleur moyen d'éviter les copies "inutiles" est encore de transmettre les objets "lourds" sous forme de référence, un peut à la manière dont j'ai transmis tous les paramètres aux différentes fonctions .

    Et, si une classe donnée (exemple : la classe Oeuvre) doit garder une trace d'un objet lourd (exemple : l'auteur), l'idéal est donc que la donnée membre en question soit maintenue sous forme de référence.

    Encore une fois, c'est d'autant plus vrai que les auteurs, les oeuvres et les exemplaires sont forcément unique, et que l'on serait donc bien inspiré de faire en sorte d'en interdire la copie.

    Au final, nous devrions modifier nos trois classes pour leur donner une forme proche 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
    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
    class Auteur{
    public:
        Auteur(std::string const & nom, std::string const & langue):
            nom_{nom}, langue_{langue}{
        }
        /* pour interdire la copie et l'affectation */
        Auteur(Auteur const &) = delete; //C++11 et ultérieur "inside"
        Auteur & operator=(Auteur const &) = delete;
        /* on veut connaitre le nom de l'auteur */
        std::string const & nom() const{
            return nom_;
        }
        /* on veut savoir dans quelle langue il écrit ses oeuvres */
        std::string const & langue() const{
            return langue_;
        }
    private:
        std::string nom_;
        std::string langue_;
    };
    class Oeuvre{
    public:
        Oeuvre(std::string const & titre, Auteur const & auteur):
            titre_{titre},auteur_{auteur}{
        }
        /* pour interdire la copie et l'affectation */
        Oeuvre(Oeuvre const &) = delete; 
        Oeuvre & operator=(Oeuvre const &) = delete;
        /* on veut connaire le titre original (dans la langue utilisée par l'auteur)
         * de l'oeuvre
         */
        std::string const & titreOriginal() const{
            return titre_;
        }
        /* on veut savoir qui a écrit l'oeuvre */
        std::string const & ecritPar() const{
            return auteur_.nom();
        }
        /* on veut savoir la langue dans laquelle il a été écrit à l'origine */
        std::string const & langueOriginale() const{
            return auteur_.langue();
        }
    private:
        std::string titre_;
        Auteur const & auteur_; // comme on ne peut plus copier l'auteur, on en garde une réféence
                                // comme on n'a aucun droit de modifier l'auteur à partir de l'oevure
                                // la référence est constante
    };
    class Exemplaire{
    public:
        /* Parce que l'on a peut-être affaire à une traduction ... ou non */
        Exemplaire(Oeuvre const & oeuvre, std::string const & titre = "", std::string const & langue=""):
            oeuvre_{oeuvre}, titre_{titre}, langue_{langue}{
        }
        /* pour interdire la copie et l'affectation */
        Exemplaire(Exemplaire const &) = delete; 
        Exemplaire & operator=(Exemplaire const &) = delete;
        /* On veut savoir qui a écrit l'oeuvre */
        std::string const & ecritPar() const{
            return oeuvre_.ecritPar();
        }
        /* on veut connaitre le titre original  de l'oeuvre*/
        std::string const & titreOriginal() const{
            return oeuvre_.titreOriginal();
        }
        /* on veut connaitre le titre de l'exemplaire actuel:
         * - soit, c'est le titre original de l'oeuvre, 
         * - soit, c'est la traduction (dans une langue donnée) de ce titre
         */
        std::string const & titre() const{
            if(titre_.empty())
                return titreOriginal();
            return titre_;
        }
        /* on veut connaire la langue original de l'oeuvre */
        std::string const & langueOriginale() const{
            return oeuvre_.langueOriginale();
        }
        /* on veut connaitre la langue spécifique de l'exemplaire 
         * - Soit c'est la langue originale de l'eouvre
         * - soit c'est la langue dans laquelle l'oeuvre a été traduit
         */
        std::string const & langue() const{
            if(langue_.empty())
                return langueOriginale();
             return langue_;
        }
    private: 
        Oeuvre const & oeuvre_; 
        std::string titre_;
        std::string langue_;
    };
    3- Comme nos classes sont devenue non copiables, la comparaison de deux objets n'a -- forcément -- plus aucun sens, vu que chaque objet est forcément unique.

    Par contre, nous pouvons comparer les informations auxquelles nous avons accès (le nom de l'auteur, le titre, la langue, ...)

    4- La comparaison de chaines de caractères est l'un des processus qui prend le plus de temps, parce que qu'elle répsente une complexité en O(n) : si deux chaines de caractères ont la même taille et sont très proches (comprends: qu'il n'y a que le dernier caractère qui change, par exemple), il faudra parcourir l'ensemble des caractères de la chaine pour pouvoir décider si elles sont identiques ou non

    Comme les auteurs, les oeuvres et les exemplaires sont uniques, nous serions sans doute bien inspirés d'ajouter une information (numérique entière, sans doute non signée), dont la comparaison est beaucoup plus rapide, à nos trois classes.

    Cette information -- unique pour chaque objet -- servirait d'identifiant unique, un peu à la manière des "clés primaires" dans une base de données, et serait utilisée en priorité lors des différentes comparaisons. Cela permettrait encore de gagner énormément en termes de performances

    Mais ca, c'est une autre histoire
    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

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

Discussions similaires

  1. Accéder aux éléments d'un tableau C
    Par pepito3364 dans le forum Assembleur
    Réponses: 19
    Dernier message: 15/06/2015, 17h17
  2. Accéder aux éléments d'un tableau associatif
    Par jejeman dans le forum AngularJS
    Réponses: 1
    Dernier message: 26/02/2015, 10h22
  3. [Débutant] accéder aux éléments d'un tableau avec l'instruction fixed
    Par goutteg dans le forum C#
    Réponses: 1
    Dernier message: 15/05/2012, 08h38
  4. accéder aux éléments d'un tableau
    Par turican2 dans le forum Langage
    Réponses: 3
    Dernier message: 12/12/2008, 15h41
  5. Réponses: 6
    Dernier message: 12/09/2007, 15h58

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