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 :

Un vecteur d'union.


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut Un vecteur d'union.
    Bonjour, j'ai décidé de faire un vecteur d'union pour pouvoir stocker différent type de données pouvant être différent à chaque fois.

    Mais je me demandais si il y aurait une façon de mettre l'affectation sur une seule ligne au lieu de faire avec des if

    J'ai le type que je veux stocker dans une variable string, exemple: float

    admettons que j'ai l'union suivante:

    union Datatype {

    int Int;
    float Float;
    string String;

    }

    et admettons que j'ai mon type de données dans une variable string comme mentionné ci-haut:

    string typeDonnee = "Float";

    Au lieu de faire:

    if (typeDonne == "Float) vec[0].Float = 5.5;

    ..

    je voudrais faire un truc du genre:

    vec[0].typeDonnee = 5.5;

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Faut pas trop fantasmer, le C++ c'est pas un langage interprété. Pour le compilo, y a autant de rapport entre la chaîne "float" et le type float, qu'entre un escargot et une chemise

    Question à trois sous : pourquoi ne pas utiliser boost::any ou un truc dans le genre ?

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    Citation Envoyé par Laurent Gomila
    Faut pas trop fantasmer, le C++ c'est pas un langage interprété. Pour le compilo, y a autant de rapport entre la chaîne "float" et le type float, qu'entre un escargot et une chemise

    Question à trois sous : pourquoi ne pas utiliser boost::any ou un truc dans le genre ?
    Ah ? je ne connais pas, qu'est-ce que boost::any ?

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    J'ai pensé a une solution, dites-moi ce que ça vaut.

    Je ferais une class Datatype dans lequel je mettrais un type union

    et je redéfinirais l'opérateur = 3 fois pour chaque type de données.

    De cette façon j'aurais un vecteur de Datatype et quand je ferais vec[0] = variable il mettrais la valeur dans le bon type automatiquement.

  5. #5
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Oublie les unions, il ne fonctionnent qu'avec les types POD, et string n'en est pas un.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    ah zut, dans ce cas, je pourrais faire comme si c'était une union, j'ai qu'a faire 3 variables dans ma classe, string, int et float bon c'est pas idéal, mais c'est pas trop lourd non plus étant donné qu'il n'y a que 3 types et ce n'est pas un projet d'entreprise c'est que pour un travail d'école, alors je crois que ça fera l'affaire.

    A moins qu'il y ait une meilleure suggestion ?

  7. #7
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Une solution serait d'utiliser un simple vecteur de strings. Les données de types différents seraient entrées et sorties à l'aide des opérateurs << et >> :
    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
    class Data
    {
    public:
      template<typename T>
      Data& operator<<(T const& x)
      {
        std::ostringstream formater;
        formater << x;
        value = formater.str();
        return *this;
      }
     
      template<typename T>
      Data& operator>>(T& x)
      {
        std::istringstream parser(value);
        parser >> x;
        return *this;
      }
     
    private:
      std::string value;
    };
     
    std::vector<Data> v(2);
    v[0] << 4.56;
    v[1] << "toto";
    double x;
    v[0] >> x;
    std::string s;
    v[1] >> s;

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    Ok

    En fait j'ai besoin d'un vecteur de vecteur de Data alloué dynamiquement

    Alors j'ai pensé faire quelque chose comme ceci:

    Data *d;
    vector<Data*> *vec = new vector<Data>();

    d = new Data(variable1);
    *vec.push_back(d);

    d = new Data(variable2);
    *vec.push_back(d);

    vector<vector*> records;
    records.push_back(vec);

    C'est que je dois faire un mini interpreteur SQL donc je dois créer une classe table dans lequel j'ai les champs et les enregistrements.

    J'ai ma méthode insert() qui reçoit en paramètre la liste des champs et valeurs sous forme d'un vecteur ou chaque élément est le nom du champs et la valeur float int ou string en string

    Je me suis fait un vecteur de pair de string pour garder le nom des champs et son type de donnée

    puis c'est là que j'ai eu l'idée de faire un vecteur pour 1 enregistrement puis un vecteur de vecteur contenant tout les enregistrements.

    C'est sûr que je pourrais tout garder en string, mais le problème c'est que lorsque je dois interpréter un select si je fais champ1 < champ2 et que c'est tout les 2 des strings, "24" < "3" donnerait vrai

  9. #9
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Ho,
    Citation Envoyé par Laurent Gomila
    Pour le compilo, y a autant de rapport entre la chaîne "float" et le type float, qu'entre un escargot et une chemise
    Et encore, certaines chemises aussi sont baveuses

    ok, je sors.

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    C'est plutôt boost variant que tu veux.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    J'ai une meilleure idée je vais faire un type Data mais avec une string et redéfinir l'opérateur <

    ou Étant donné que c'est qu'une string ordinaire, peut-on redéfinir l'opérateur < pour les string sans faire une nouvelle classe ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Quelques remarques d'ordre générale:

    -Dans la plupart des cas, il n'est pas intéressant d'allouer dynamiquement un conteneur de la STL...:

    Crée le de manière tout à fait statique, que ce soit dans une fonction ou dans une classe, et
    • passe le par référence (constante ou non) aux fonctions qui n'y ont pas accès
    • renvoie-le par référence (constante ou non) si c'est le retour d'une fonction membre de la classe qui a acces au vecteur sans le modifier
    • renvoie le de manière classique si c'est le retour d'une fonction dans laquelle il est créé (pour modification "temporaire", par exemple)

    De la meme manière, les cas dans lesquels il est intéressant d'introduire un élément alloué dynamiquement dans un conteneur de la STL sont relativement limité également...

    Si, pour pouvoir envoyer l'élément de ton conteneur à une fonction de bibliothèque, il apparait nécessaire de disposer d'un pointeur sur cet élément, de prendre "l'adresse" de l'élément en cas de besoin

    L'une des raisons principales de cette deuxième remarque est qu'il suffit, pour supprimer un élément de ton conteneur (ou pour le vider) d'utiliser la fonction membre qui va bien (erase ou clear), alors qu'il faudra penser à travailler en deux temps avec des éléments alloués dynamiquement:
    • libérer la mémoire pointée par l' (les)élément(s)
    • supprimer l'(les)élément(s) avec la fonction membre qui va bien


    Voici un code simple pour t'en convaincre:
    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
     
    #include <iostream>
    #include <vector>
    std::vector<int> CreateVector()
    {
        std::vector<int> ret;
        for(int i=0;i<5;i++)
            ret.push_back(i);
        return ret;
    }
    void AffichVector(std::vector<int>& vect)
    {
        for(unsigned int i=0;i<vect.size();i++)
            std::cout<<vect[i]<<"\t"<<&vect[i]<<std::endl;
    }
    void Ajoute5elem(std::vector<int>& vect)
    {
        unsigned int taille=vect.size();
        unsigned int final=taille+5;
        for(unsigned int i=taille;i<final;i++)
            vect.push_back(i);
    }
    // ajoute un élément au vecteur
    void AjouteValeur(std::vector<int>& vect, int val)
    {
        vect.push_back(val);
    }
    int main()
    {
        std::vector<int> vect=CreateVector();
    	std::cout<<"premier affichage "<<std::endl;
    	AffichVector(vect);
    	std::cout<<"ajoute 5 elements"<<std::endl;
    	Ajoute5elem(vect);
    	std::cout<<"deuxième affichage"<<std::endl;
    	AffichVector(vect);
    	//ajoute d'autres éléments
        AjouteValeur(vect,100);//Remarque: aucune de ces trois valeurs
        AjouteValeur(vect,101);//n'existe réellement dans main ;)
        AjouteValeur(vect,102);//elles sont créées lors de l'appel de la fonction
                               //et cessent donc d'exister lorsque la fonction est
                               //quittée ;)
        std::cout<<"affichage final"<<std::endl;
    	AffichVector(vect);
    	return 0;
    }
    NOTA:j'ai utilisé un "simple" vector et un "simple" int, mais cela fonctionne tout aussi bien avec les conteneurs et/ou les éléments plus complexes

    Si l'utilisation de pointeur doit etre envisagée dans un conteneur STL, ce sera beaucoup plus parce qu'on souhaite pouvoir vérifier que l'on accede bien à un élément donné alors que d'autres éléments peuvent avoir exactement les memes valeurs (comme clé dans une map, par exemple)
    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

  13. #13
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Comme dit Loufoque, utilise boost.variant : http://www.boost.org/doc/html/variant/tutorial.html

    Ca offre plus de garanties qu'un pointeur void ou boost::any, dans le cas présent. Ca fait une vérification statique des types, c'est ça qui est puissant.

    Un exemple de code qui ferait ce que tu veux :

    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 <vector>
    #include <string>
    #include <boost/variant.hpp>
     
    // Définition de ton type de données
    typedef boost::variant<int, float, std::string> DataType;
     
    //
    // Visiteur qui sert à afficher les données
    //
    // Le visiteur est à considérer comme une fonction ou un foncteur
    // Il faut traiter tous les types contenus dans le type union
    // Le paramètre template de static_visitor sert à préciser le type de la valeur de retour
    // Ici, c'est void donc on ne met rien, mais sinon il faut préciser
    class display_visitor : public boost::static_visitor<>
    {
    public:
        template <typename T>
        void operator()(const T& t) const
        {
            std::cout << t << std::endl;
        }
    };
     
     
    // Visiteur qui affecte 5.5f à tous les flottants, sinon rien du tout
    class example : public boost::static_visitor<>
    {
    public:
        template <typename T>
        void operator()(const T&) const
        {
        }
     
        void operator()(float& f) const
        {
            f = 5.5f;
        }
    };
     
     
    int main()
    {
        // On crée un vecteur de ton type union
        vector<DataType> v;
     
        v.push_back(25);
        v.push_back(3.0f);
        v.push_back("bonjour");
     
        // On applique le visiteur d'affichage pour chaque valeur du vecteur
        for (size_t i = 0; i < v.size(); ++i)
        {
            boost::apply_visitor( display_visitor(), v[i] );
        }
     
        // On applique le modificateur..
        for (size_t i = 0; i < v.size(); ++i)
        {
            boost::apply_visitor( example(), v[i] );
        }
     
        std::cout << std::endl;
     
        // On affiche le contenu modifié avec une
        // autre méthode, avec création d'un foncteur à la volée
        display_visitor visitor;
        for_each(v.begin(), v.end(), boost::apply_visitor( visitor ));
     
        return 0;
    }
    Et ça t'affiche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    25
    3
    bonjour
     
    25
    5.5
    bonjour
    Ce qui est bien ce que l'on veut. Plus de détails dans le lien filé.

    Perso, j'ai utilisé ça pour faire un interpréteur, combiné avec boost.spirit, c'est très pratique.

  14. #14
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Ca offre plus de garanties qu'un pointeur void ou boost::any
    Ça offre pas vraiment plus de garanties que boost any.
    C'est juste qu'avec variant, l'implémentation peut être plus performante et on peut utiliser des visiteurs, qui nous permette en particulier de récupérer le type réel de l'objet dans le variant.

  15. #15
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    J'entendais ça dans le sens où :

    Boost.Variant guarantees the type of its content is one of a finite, user-specified set of types.

    Et dans ce cas de figure, la vérification statique des types via les visiteurs, plus que les performances, c'est une meilleure conception, proche de ce qu'on a dans les langages fonctionnels.

  16. #16
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    On pourrait très bien le faire avec boost.any aussi si on pouvait faire des fonctions virtuelles templates.

    proche de ce qu'on a dans les langages fonctionnels.
    C'est plus lié au typage dynamique qu'à un caractère fonctionnel quelconque...

  17. #17
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par loufoque
    On pourrait très bien le faire avec boost.any aussi si on pouvait faire des fonctions virtuelles templates.


    C'est plus lié au typage dynamique qu'à un caractère fonctionnel quelconque...
    Plutôt du filtrage de motif en fait =).

Discussions similaires

  1. Fonction union sur plusieurs vecteurs
    Par neptune2024 dans le forum MATLAB
    Réponses: 3
    Dernier message: 09/06/2009, 11h02
  2. Récuperer les coordonnées d'un vecteur
    Par kerzut dans le forum OpenGL
    Réponses: 5
    Dernier message: 15/04/2003, 11h51
  3. Créer une vue pour trier une requete UNION ?
    Par Etienne Bar dans le forum SQL
    Réponses: 3
    Dernier message: 03/01/2003, 20h22
  4. Zoom sur des vecteurs ou lignes
    Par mat.M dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 25/11/2002, 10h40
  5. matrices * vecteur
    Par delire8 dans le forum Algorithmes et structures de données
    Réponses: 15
    Dernier message: 07/09/2002, 14h15

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