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 :

Création de variable avec un type variable !


Sujet :

C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut Création de variable avec un type variable !
    Bonjour à tous,

    Je cherche à écrire une fonction qui prenne en argument le string 'type', qui doit être choisi dans la liste : char, short int, int, float etc... (vous m'avez compris), et qui déclare une variable 'x' du type choisi.
    Simplissime !?
    Et pourtant je n'y arrives absolument pas !


    Enfin ce n'est pas exacte, un truc de ce style peut marcher :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if ( "char".compare(type) == 0) 
    {
     char x; else if ( "short int".compare(type) ==0 )
                      { 
                      short int x; else if (blablabla...
                      }
    }
    Mais je n'insiste pas, vous avez compris : c'est lourd et en plus ça compile très difficilement ( i.e : que si 'x' est déclaré au préalable, quitte à la re-déclarée, parce que sinon la construction conditionnelle ne permet pas à 'x' d'être déclarée à coup sur... ou en tout cas c'est ce que pense le compilateur )


    J'ai cherché partout de l'aide sur le sujet, genre comment déclarer les variables, typer les variables etc etc, mais toutes les aides que je trouve se référent à des trucs bateaux du style "int myfirstvariable" ou autre...


    Si quelqu'un à une solution toute faite à me mettre sous le nez (même un bout de tuto ou un truc qui m'avance), ou alors une petite idée je suis preneur.


    Merci beaucoup d'avance,
    Cordialement,
    Mark.


    PS : ci-dessous l'ersatz de code que j'ai déjà écrit ; J'ai marqué et mis en commentaire le morceau qui est évidemment faux, mais il montre bien ce que je cherches à faire au moins ... vous voyez non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
      string type;
      string names[] = {"char", "short int", "int", "float", "double"};
     
      printf("Chose type of stack among : char, short int, int, float, double\n");
      getline( cin, type);
     
      for (int i=0; i < 5; i++)
      {
        if ( names[i].compare( type ) == 0 )
    	{
    	  //names[i] s;                                   <-- Le problème est ici    
    	}
      }

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Ce genre de chose peut être fait a l'aide de l'a métaprogramation. va faire un tour ici : http://loulou.developpez.com/tutoriels/cpp/metaprog/ .

    Cela dit, je ne suis pas convaincu que tu attaques ton problème de manière pertinente.

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    template tout court ?
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

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

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Si tu n'as que des types aussi simples que ça, tu peux utiliser une union.

    Sinon, si t'as besoin de types non POD (genre std::string), tu peux regarder Boost.Variant : http://www.boost.org/doc/libs/1_36_0...l/variant.html

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 378
    Points : 23 669
    Points
    23 669
    Par défaut
    Citation Envoyé par Marcool Voir le message
    Je cherche à écrire une fonction qui prenne en argument le string 'type',
    Comme dit plus haut, c'est le principe du template, mais ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      printf("Chose type of stack among : char, short int, int, float, double\n");
      getline( cin, type);
    C'est ce que je craignais.

    Tu veux faire cela au runtime. Or, ce que tu cherches à faire est une fonction du compilateur ! Tu ne peux donc pas faire appel à ses services après la compilation, une fois le programme lancé, ce qui est normal.

    De là, tu as trois solutions :

    • Tu utilises un langage interprété. Ils proposent pratiquement tous une fonction eval bien pratique (Perl, Shell, et même le BASIC M$ de 1986 :-).
    • Tu écris une seule fois un template pour ta fonction, et ensuite, comme ta liste propose une nombre d'éléments fini, tu fais une seule fois un switch en énumérant ces mêmes éléments
    • Tu regardes du côté du RTTI, mais ça ne résoudra pas tous tes problèmes.

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    La solution la plus "simple" pour le PO me semble boost::variant... Mais il faut récupérer boost, ou du moins variant et ses dépendances.

    Mais ce que tu veux faire est en général très mal vu ... Tu peux nous expliquer dans quel cadre tu as besoin d'une telle fonctionnalité pour ton programme ?

  7. #7
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Tout d'abord merci à tous pour vos réponses avisées. Pour vous re répondre à présent, dans un désordre total :

    Mais ce que tu veux faire est en général très mal vu ... Tu peux nous expliquer dans quel cadre tu as besoin d'une telle fonctionnalité pour ton programme ?
    Pourquoi est-ce que ce serrait mal vu ?! J'ai du mal à voir ce qui peut te faire réagir comme ça la dedans Alp ? Si vous voulez vraiment savoir, j'étais parti pour faire un proof of concept du buffer overrun classique, genre :

    "Choisissez un type de variable ..."
    'char'
    "Entrez une valeur numérique ..."
    '657352719373947'
    "Voici la variable stockée dans la variable :
    '-543'
    "Buffer overrun détecté !"

    C'est vrai qu'on peut faire ça en déclarant directement une variable et tout et tout, mais je suis un fana d'interactivité, et j'avais envi que le truc soit portable... En fait je me suis surtout monté à la tête le fait de ne pas pouvoir choisir après l'exécution le type de la variable !




    Tu utilises un langage interprété. Ils proposent pratiquement tous une fonction eval bien pratique (Perl, Shell, et même le BASIC M$ de 1986 :-).
    J'étais à peu près persuadé que quelqu'un me trouverait une solution dans un autre langage, c'est vrai que je pourrais, mais je suis têtu et j'ai voulu finir en C++ ce que j'avais commencé en C++! Mais je vais regarder du coup (peut-être pas dans le BASIC quand même, bien que j'en suis persuadé ça doit avoir ses avantages, on se comprend$ :-), merci là encore.



    Tu écris une seule fois un template pour ta fonction, et ensuite, comme ta liste propose une nombre d'éléments fini, tu fais une seule fois un switch en énumérant ces mêmes éléments
    Eh... ça peut vraiment marcher ça ? (oui oui je vais essayer je sais :-) Ah ouai en fait ça marche (je pensais que ça posait des problèmes de substitution dans le template mais en fait non c'est logique et simple!) Je vois maintenant. Ça revient quand même à utiliser la lourdingue construction conditionnelle décrite dans mon premier post (ok le switch rend ça bien plus propre), mais c'est fonctionnel au moins ! Merci beaucoup Davidbrcz et Obsidian !




    Tu regardes du côté du RTTI, mais ça ne résoudra pas tous tes problèmes.
    D'après ce que je lis , le C++ n'est pas sensé comporter de RTTI... ou en tout cas ça sera du bidouillage non?




    La solution la plus "simple" pour le PO me semble boost::variant...
    Eh ouai... j'avoue que je ne comprends pas trop ce que je suis sensé faire avec variant. Mais il se peut que je n'ai pas bien saisi quel est le rôle de cette fonction... Il me semble qu'elle sert à créer une union un peu spéciale, qui accepte de stocker des types non POD... Non? Si c'est le cas, puisque mes types sont tous POD de toute façon si ça marche avec union (pas encore testé...) alors j'ai pas besoin de variant, si?



    Si tu n'as que des types aussi simples que ça, tu peux utiliser une union.
    Ouai je n'ai que des types simples... et oui une union me semble être une bonne idée. Ça ne me permettra pas de me débarrasser du switch après mais au moins j'ai pas besoin de créer un template avant, une simple union suffit.
    Sauf que comme le but est de faire déborder la variable... et qu'une union se voit réserver l'espace du type le plus gros qu'on pourrait lui demander de contenir, je ne la ferai déborder que quand quelque chose de plus gros qu'un double sera saisi... ce qui n'est pas mon but.
    Dommage, l'idée était de loin la plus propre !



    Cela dit, je ne suis pas convaincu que tu attaques ton problème de manière pertinente.
    Eh... la définition de pertinente est quelque chose de vraiment très subjectif, et je t'en prie deadalnix si tu as plus "pertinent" à proposer comme approche je suis preneur.




    Mot de la fin : merci beaucoup à tous d'avoir pris le temps de me répondre. Je pense avoir trouvé comment je vais faire ça (template puis switch)... je posterai peut-être ce que je fais finalement plus tard dans la soirée pour référence.

    Cordialement,
    Mark.

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    Citation Envoyé par Marcool Voir le message
    Eh... la définition de pertinente est quelque chose de vraiment très subjectif, et je t'en prie deadalnix si tu as plus "pertinent" à proposer comme approche je suis preneur.
    La ligne au dessus.

  9. #9
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Ok deadalnix...
    sauf que la page que toi même me dit d'aller voir contient la raison qui fait que cette approche n'est pas pour moi :

    Un autre inconvénient est qu'ici tout ce que nous allons écrire devra être connu du compilateur : certaines données que nous allons manipuler ne pourrons assurément pas être entrées par l'utilisateur lors de l'execution.
    ...or je vise l'interactivité justement.

    Si tout devait être su au moment de la compilation je ferais simplement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include <iostream>
    using namespace std
     
    char x
    int main()
    {
    cout << "Entrez une valeur numérique svp." << endl;
    cin >> x;
    cout << "La valeur enregistrée est : " << x << endl;
    return 0;
    }
    et si la valeur entrée est supérieure à 255 (on suppose le char non signé) alors on véra de suite le buffer overrun... mais ce n'est pas ça que je veux faire.

    Merci quand même ; je suis sûr que la métaprogrammation pourra m'être utile à une autre occasion.

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Points : 2 548
    Points
    2 548
    Par défaut
    sauf que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<class T> void traitex(T& x){
       truc;
       machin;
    }
    et :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    switch(type){
       case INTEGER:
          traitex<int>(x);
          break;
        case BLOP:
           traitex<blop>(x);
          ...
    }
    C++ est un langage typé, tu y échaperas pas.

  11. #11
    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
    Avant de chercher comment le faire, il faudrait peut-être que tu définisses exactement ce que tu veux. Avec ce que tu as dis, tu peux aussi bien vouloir un interpréteur C++ détectant toutes les comportements indéfinis que quelque chose de beaucoup plus simple. Suivant l'ampleur de ce que tu veux exactement, ce n'est pas les mêmes techniques à mettre en oeuvre.

    En passant, un overflow ce n'est pas un buffer overrun...
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    En passant, un overflow ce n'est pas un buffer overrun...
    Eh... il me semble que c'était synonyme au moins :

    In computer security and programming, a buffer overflow, or buffer overrun, is an anomalous condition where a process attempts to store data beyond the boundaries of a fixed-length buffer.
    cf http://en.wikipedia.org/wiki/Buffer_overflow

    (c'est même mieux que ça : la page pour Buffer_overrun redirige vers celle de Buffer_overflow)



    C++ est un langage typé, tu y échapperas pas.
    Ouai c'est vrai. Je me plie :-) Au moins j'ai appris ça "the hard way" et je ne l'oublierai pas !


    En tout cas j'ai pas mal appris grâce à vous tous, merci encore. Je pense qu'on peut en gros clore le topic...
    Bonne continuation.
    Mark.

  13. #13
    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
    Tu n'as pas de buffer overflow ou overrun, tu as un overflow dans un calcul en entier.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  14. #14
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Tu n'as pas de buffer overflow ou overrun, tu as un overflow dans un calcul en entier.
    Je ne vois pas où est le calcul là dedans (stocker données dans un buffer, i.e variable, allouée précédemment puis recracher valeur...) et ça semble convenir parfaitement à la définition du buffer overrun mais si tu y tiens... on va appeler ça un overflow (littéralement c'est vrai que ça "déborde" ang : overflow, je ne nie pas... donc pourquoi pas !)

    En général je ne pinaille pas trop sur le vocabulaire ...

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

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par Marcool Voir le message
    Je ne vois pas où est le calcul là dedans (stocker données dans un buffer, i.e variable, allouée précédemment puis recracher valeur...) et ça semble convenir parfaitement à la définition du buffer overrun mais si tu y tiens... on va appeler ça un overflow (littéralement c'est vrai que ça "déborde" ang : overflow, je ne nie pas... donc pourquoi pas !)

    En général je ne pinaille pas trop sur le vocabulaire ...
    Tu ne pourras jamais savoir que tu as dépassé la capacité de ton entier, il faut agir au niveau du parseur, c'est ce que tu ne comprends pas.

    Le parseur il doit surement faire des calculs tout bêtes, sans tenir compte de la capacité de représentation.

  16. #16
    Futur Membre du Club
    Inscrit en
    Août 2008
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Bon fondamentalement là on est un peu hors sujet et c'est pas trop ce qui m'intéresse, mais pour ne pas laisser le débat ouvert :
    Dans mon idée, quand on déclare une variable, on lui donne un type ; au moment de l'exécution la machine réservera donc une portion de mémoire de la taille déterminée par le type choisi, pour cette variable.
    Après ce qu'on y met ou pas n'est pas tellement la question ici, mais l'overflow apparait lorsqu'on essai de mettre quelque chose de trop "gros" dans la variable, par rapport au type qu'on avait déterminé précédemment, par exemple, le code :

    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
    #include <iostream>
     
    using namespace std;
     
    int main()
    {
    int x;
     
     
    cout << "Choisissez une valeur a stocker dans la variable svp" << endl;
    cin >> x;
    cout << "La variable contient : " << x << endl;
     
    return 0;
    }
    Donne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ g++ -o exec ./temp.cpp 
     
    $ ./exec 
    Choisissez une valeur a stocker dans la variable svp
    7876
    La variable contient : 7876
     
    $ ./exec 
    Choisissez une valeur a stocker dans la variable svp
    45432222346
    La variable contient : -1073742504
    Que ce soit le parseur ou autre chose qui détermine comment c'est fait ne m'importe pas vraiment. La raison pour laquelle j'ai ouvert ce topic c'est pour savoir si au moment de l'exécution du programme on pouvait choisir le type d'une variable.
    On m'a répondu : non, la variable est typée par le compilateur. Fin du débat. Merci quand même de ton apport HanLee.

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

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par Marcool Voir le message
    Bon fondamentalement là on est un peu hors sujet et c'est pas trop ce qui m'intéresse, mais pour ne pas laisser le débat ouvert :
    Dans mon idée, quand on déclare une variable, on lui donne un type ; au moment de l'exécution la machine réservera donc une portion de mémoire de la taille déterminée par le type choisi, pour cette variable.
    Après ce qu'on y met ou pas n'est pas tellement la question ici, mais l'overflow apparait lorsqu'on essai de mettre quelque chose de trop "gros" dans la variable, par rapport au type qu'on avait déterminé précédemment, par exemple, le code :

    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
    #include <iostream>
     
    using namespace std;
     
    int main()
    {
    int x;
     
     
    cout << "Choisissez une valeur a stocker dans la variable svp" << endl;
    cin >> x;
    cout << "La variable contient : " << x << endl;
     
    return 0;
    }
    Donne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ g++ -o exec ./temp.cpp 
     
    $ ./exec 
    Choisissez une valeur a stocker dans la variable svp
    7876
    La variable contient : 7876
     
    $ ./exec 
    Choisissez une valeur a stocker dans la variable svp
    45432222346
    La variable contient : -1073742504
    Que ce soit le parseur ou autre chose qui détermine comment c'est fait ne m'importe pas vraiment. La raison pour laquelle j'ai ouvert ce topic c'est pour savoir si au moment de l'exécution du programme on pouvait choisir le type d'une variable.
    On m'a répondu : non, la variable est typée par le compilateur. Fin du débat. Merci quand même de ton apport HanLee.
    Oui mais on t'as dit qu'il y avait une certaine flexibilitée apportée avec les unions, ou les variants, qui te permettent de typer dynamiquement ta variable dans un ensemble fini.
    Comme du polymorphisme.

    Si tu agis au niveau du parseur, tu peux détecter l'overflow, en comptant le nombre de caractères, puis en analysant plus finement.

  18. #18
    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
    Points : 4 625
    Points
    4 625
    Par défaut
    Ce que tu veux, en fait, c'est un type entier avec une taille dynamique.
    C'est vraiment un cas particulier... Y'a plein de bibliothèques qui font ça.
    Boost ftw

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

Discussions similaires

  1. Utilisation de Ctype avec un type variable
    Par Tommy57 dans le forum Windows Forms
    Réponses: 5
    Dernier message: 09/07/2013, 09h41
  2. Acceder à une variable avec une autre variable
    Par kisscoool dans le forum ActionScript 3
    Réponses: 4
    Dernier message: 21/05/2008, 12h52
  3. types variables avec typedef
    Par Haenou dans le forum C
    Réponses: 4
    Dernier message: 16/04/2008, 09h07
  4. cast avec un type variable
    Par Axwell dans le forum C++
    Réponses: 2
    Dernier message: 13/11/2007, 10h06
  5. variable avec un type non défini
    Par gign2585 dans le forum Windows Forms
    Réponses: 4
    Dernier message: 24/05/2007, 18h10

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