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 :

Tableaux de types multiples


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut Tableaux de types multiples
    Bonjour à tous,

    tout d'abord voici ce que j'aimerais faire :

    je lis un message où je récupère entre autre des paramètres
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    boucle tant que(pas fin message)
    {
    lire type du paramètre
         si type==int alors lire le paramètre, le caster en int et le stocker dans param
         si type==bool alors lire le paramètre, le caster en bool et le stocker dans param
    }
    Donc voilà, si ca boucle, le paramètre param va etre ecrasé par la nouvelle lecture

    Donc j'ai pensé à la solution du tableau qui serait de différents types,
    alors à chaque boucle j'incrémente une variable, et j'ecris ds param[0] puis param[1] etc...

    Si il y a un moyen plus simple, arrêtez moi tout de suite ...

    Sinon, comment fait-on ca ?

    J'ai réussi à trouver la notion de conteneur, auquel cas il y aurait typeid() qui permettrait de récupérer le type, ce qui m'arrangerait pour un autre truc!

    Suis-je sur la bonne voie ?

  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
    Tu ne peux pas avoir un tableau contenant des éléments de différents types.

    Il faudrait que tu nous expliques un peu le contexte, mais si stocker des types différents est vraiment la solution à ton problème, alors tu as boost.variant ou boost.any qui peuvent ty 'aider.

  3. #3
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    Je ne pense pas que boost.variant m'aide dans mon cas.
    Je reexplique (pas évident d'etre clair ) :
    Je recupere un parametre d'un type quelconque, et je veux le mettre dans une variable.
    Faisant ca dans une boucle, je ne peux pas declarer une seule variable, meme de type multiple, puisque au deuxieme passage de la boucle, j'ecrase le travail du premier passage de la boucle.

    Bon je poste le code parce que la je m'enfonce ...

    je lis ce message :
    string msgBuf("fMessageBoxA@1930@194Your function is working@194Hey Dude@193MB_OK");

    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
    string funcName(readName(msgBuf));
    	LPCSTR funcNameL;
    	funcNameL=funcName.c_str(); // converts String into LPCSTR
    	int loop=0;
    ->	while(msgbuf[ltr]!='\0')
    	{
     
     
    		string paramType(readType(msgBuf));
    		std::istringstream iss( paramType );
    		int paramTypeInt;
    		iss >> paramTypeInt;
     
    		string paramValue;
     
    		switch (paramTypeInt)
    		{
    			case 193 :
    				paramValue=readName(msgBuf);
    				break;
    			defaut :
    				break;
    		}
     
    	}
     
    	FCTX<int, char*, char*, unsigned int>::type        Fn_Ptr;
    	Fn_Ptr = (FCTX<int, char*, char*, unsigned int>::type )GetProcAddress(ModId, funcNameL);
    	Status = Fn_Ptr(0, "Your function is working", "Hey dude", MB_OK);
    	printf ("After function call, status = %i (1 means ok)\n", Status);
    	cout<<" Address pointer : "<<Fn_Ptr<<" !! "<<endl;
    	cout<<funcNameL<<" ( "<<paramType<<','<<paramValue<<" );"<<endl;
    c'est donc paramValue que je recupere. J'aimerais reutiliser paramValue dans la ligne
    Status = Fn_Ptr(0, "Your function is working", "Hey dude", MB_OK);
    pour avoir
    Status = Fn_Ptr(paramValue1, paramValue2, paramValue3, paramValue4);
    Donc comment faire pour recuperer mes differents parametres, les mettre dans 4 paramValue differents ? J'avais pensé à un espece de tableau acceptant des types differents, mais comment faire alors?

    Merci pour votre aide
    Je reviens demain si j'ai besoin d'apporter des precisions

  4. #4
    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
    Mais là les types sont parfaitement connus, ainsi que le nombre d'éléments. Donc il te suffit de déclarer les 4 variables qu'il te faut.

    Tu ne pourras plus utiliser une boucle, mais il suffit de placer ton code de lecture dans une fonction (template) et de l'appeler pour chacune de tes variables.

    Sinon, si tu tiens vraiment à avoir un tableau, tu peux utiliser boost.any.

  5. #5
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    j'avais préparé un exemple avec des conteneur... mais là il te suffit simplement de découper ta string avec strtok ou en c++ (avec string.find()) et de stocker les différents paramètres dans des strings ou des chaines de caractères.

    Exemple:
    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
     
     
    string message= "fMessageBoxA@1930@194Your function is working@194Hey Dude@193MB_OK";
     
    char *explore = (char*)(void*)message.c_str();
    int num;
     
    /* on cherche le nombre de @ */
    for(num = 1; *explore != 0; ++explore)
    {
      if (*explore == '@') ++num;
    }
     
    /* création du tableau */
    string params[num];
     
    /* on refait une boucle , cette fois pour placer les éléments*/
    int i, j, k;
    for (i = 0, j = message.find('@', i), k=0; k < num; ++k, i=j+1, j=message.find('@'))
    {
      param[k] = message.substr(j-i);
    }
     
    /*
      maintenant on a le tableau param
      en fait ca aurait été beaucoup plus simple
      avec strtok
      */

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Et si tu as 150 options, boost.program_options est un choix possible.
    Lectures connexes (pour des solutions plus génériques):
    http://www.developpez.net/forums/sho...=1#post1588859
    http://www.developpez.net/forums/sho...d.php?t=186236
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    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
    Je ne pense pas que boost.variant m'aide dans mon cas.
    Pourtant, si.
    C'est exactement ce que tu veux d'après la demande de ton premier message.

    Sauf que boost.variant ne l'implémente pas comme ça (tu trouveras ce genre de d'interface avec boost.any) mais d'une meilleure manière, plus propre, plus performante (car la recherche du type doit être en O(log n) a priori et non pas en O(n)) et en plus, permet de faire un genre de duck typing avec les templates.

  8. #8
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    Citation Envoyé par coyotte507
    j'avais préparé un exemple avec des conteneur... mais là il te suffit simplement de découper ta string avec strtok ou en c++ (avec string.find()) et de stocker les différents paramètres dans des strings ou des chaines de caractères.

    Exemple:
    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
     
     
    string message= "fMessageBoxA@1930@194Your function is working@194Hey Dude@193MB_OK";
     
    char *explore = (char*)(void*)message.c_str();
    int num;
     
    /* on cherche le nombre de @ */
    for(num = 1; *explore != 0; ++explore)
    {
      if (*explore == '@') ++num;
    }
     
    /* création du tableau */
    string params[num];
     
    /* on refait une boucle , cette fois pour placer les éléments*/
    int i, j, k;
    for (i = 0, j = message.find('@', i), k=0; k < num; ++k, i=j+1, j=message.find('@'))
    {
      param[k] = message.substr(j-i);
    }
     
    /*
      maintenant on a le tableau param
      en fait ca aurait été beaucoup plus simple
      avec strtok
      */


    Salut,
    c'est exactement ce que fait ma fonction readName ou readType, elle lit ma chaine msgbuf et stocke dans des strings. Mais ma boucle me sert aussi a transformer mes strings en le type defini dans msgbuf (ce sont les codes 193 ou 194 ca correspond a des types, mon maitre de stage veut que ce soit des numeros, alors on met des numeros)
    Et mon msgbuf n'est pas fixe, normalement c'est un message que je recois par ethernet, et il est different a chaque fois, c'est juste un exemple ici pour bosser...

  9. #9
    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
    Vu que de toute façon tu connais les types (tu passes tes valeurs à une fonction dont le prototype est bien défini), pourquoi ne pas garder tes valeurs sous forme de chaîne et les convertir uniquement au moment de l'appel (là où tu connais le type), par exemple avec boost.lexical_cast ?

  10. #10
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    resalut
    etant donné que je galere un peu à comprendre ce que vous me proposez, j'ai pensé a un moyen un peu moins joli sans doute, mais que je comprends
    Mais pour éviter des dizaines de lignes de codes, y aurait-il un moyen selon le numero de passage dans une boucle, de declarer une variable genre nom+numero


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int loop=1;
    boucle while
    {
    int declaration1;  // au premier passage
     
    loop++;
    }
    puis

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    boucle while
    {
    int declaration2;  // au deuxieme passage
     
    loop++;
    }
    Ca doit etre possible de faire ca non ?

  11. #11
    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
    Non ce n'est pas possible. Ou plutôt si, via un tableau (mais là on retombe dans le problème initial).

    Qu'est-ce que tu ne comprends pas avec les méthodes proposées ?

    Sinon il y a un truc que je ne comprends pas. Le types des paramètres est donné avec ceux-ci (via un nombre), ce qui signifie que le programme n'est pas censé connaître à l'avance ces types. Pourtant après l'extraction des valeurs tu vas bien finir par appeler une fonction, et cette fonction tu es bien obligé de savoir à l'avance quels types elle prend en paramètre, non ?

  12. #12
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    oui, le message contenant numero de type et parametre est envoyé par quelqu'un qui sait quels parametres prend la fonction a appeler. Le message est censé etre correct. Je dois simplement dans mon programme interpreter le message et appeler la fonction indiquee dans le message.
    Et c'est pas evident.
    Et en plus pas de chance la solution que je pensais ne foncionne pas, le compilateur me dit que mes variables (declarees a l'interieur d'un switch lui meme a l'interieur d'un while) ne sont pas declarees..
    Ca me casse un peu mon delire la


    --> mais je dois pouvoir regler ca avec une declaration generique, un template

  13. #13
    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
    oui, le message contenant numero de type et parametre est envoyé par quelqu'un qui sait quels parametres prend la fonction a appeler
    Ce que je veux dire, c'est que dans ton code tu vas bien avoir des types écrits en clair, non ? Comme dans ton premier exemple, où on voit bien que les paramètres devront être respectivement de type int, char*, char*, et unsigned int.

    Pour ton problème de switch, c'est juste une histoire de portée, place tes bouts de code (ceux de chaque case) entre accolades et ça fonctionnera.

  14. #14
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    Oui mais attention le code n'est pas fini.
    Au final, la ou tu vois ecrit int,char*,char*,unsigned int dans mon 1er exemple, ca doit s'en aller et etre remplacé par un truc generique, du style typeid(paramValue) par exemple...
    Tu comprends ?


    (j'ai beau rajouter des accolades ca change pas...toujours undeclared)

  15. #15
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Une classe conteneur est simple à réaliser:

    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
     
    template<class T>
    class conteneur(T &var)
    {
      public:
        T item;
        conteneur *pApres;
        conteneur *pAvant;
     
        conteneur(T &var);
        ~conteneur();
        template <class M>
        newconteneur(M var);
       /*tu dois définir un opérateur [] pour accéder à l'item du nieme membre
       a partir du début*/
    }
     
    conteneur::conteneur(T &var)
    {
      item = var;
      pApres = NULL;
      pAvant = NULL;
    }
     
    conteneur::~conteneur
    {
      delete pApres;
    }
     
    template <class M>
    conteneur *conteneur::newconteneur(M &var)
    {
      conteneur *tmp = pApres;
      pApres = new conteneur(var);
      pApres->pAvant = this;
      if (tmp != NULL)
      {
        pApres->pApres = tmp;
        tmp->pAvant = pApres;
      }
      return pApres;
    }
    et après:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int j;
    string str;
    long k;
    conteneur *pCont;
     
    conteneur cont(j);
    pCont = cont.newconteneur(str);
    pCont = pCont.newconteneur(k);
    Tu as donc le conteneur d'origine dans cont, et celui 'courant' dans pCont. Tu dois maintenant créer un opérateur [], qui à partir du premier conteneur, te retourne le nieme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    conteneur& conteneur::operator[] (int i)
    Après tu accèdes à la valeur:

    Je pense que tu peux le faire

  16. #16
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    salut, désolé de ne pas avoir répondu plus tôt.
    J'ai parlé avec mon maître de stage, il a changé d'avis puisque maintenant il accepte d'écrire texto le nom des types dans mon message, donc ca évite une énumération de tous les types existants (ouf) si et seuleöent si je trouve une fonction magique qui me traduit le type donné en string en un type réel.

    du genre :
    string monMessage = "int value"
    j'obtiens grace a mon programme :
    string param1 = "int" et string param2="value"
    ds mon programme j'ai une fonction qui fait :
    VraiType(param1) param2
    qui se traduit par un beau int value à la compilation.

    alors j'ai regardé boost.any, boost.program_options, et boost.lexial_cast, mais je suis pas convaincu qu l'un d'entre eux me résolve mon problème, je me trompe?

  17. #17
    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
    maintenant il accepte d'écrire texto le nom des types dans mon message, donc ca évite une énumération de tous les types existants (ouf)
    Ca ne change absolument rien, que ce soit un entier quelconque ou directement le nom du type, ça n'a pas plus de sens pour ton code C++, il faudra de toute façon trouver un moyen de les faire correspondre.

  18. #18
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    tu veux dire qu'il n'existe pas de fonction qui transforme le nom d'un type en son type alors ?
    parce que si ca existe ca change radicalement mon code!

  19. #19
    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
    Citation Envoyé par Xorgnem
    tu veux dire qu'il n'existe pas de fonction qui transforme le nom d'un type en son type alors ?
    parce que si ca existe ca change radicalement mon code!
    Non... Ca n'est possible typiquement qu'avec les langages interprétés. N'oublie pas que "int", "char" etc. n'ont plus aucun sens après compilation, il ne reste que du code machine avec des 0 et des 1

  20. #20
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Juin 2007
    Messages : 33
    Par défaut
    Et si je crée ce genre de fonction, ce serait une fonction template avec un liste de if

    si je l'appelle whichType
    ca ferait
    if "int" return <int>1;
    if "string" return <string>"un";


    apres, je fais typeof(whchType("int")) value et ca revient au meme ?
    Je sais pas, c'est pas possible c'est ca ?

Discussions similaires

  1. [Tableaux] Programme de multiplication enfant
    Par isa150183 dans le forum Langage
    Réponses: 12
    Dernier message: 02/08/2006, 23h16
  2. [Tableaux] Le type Ensemble existe-t-il ?
    Par petitnuage dans le forum Langage
    Réponses: 3
    Dernier message: 08/06/2006, 20h21
  3. [Tableaux] bouton radio multiples
    Par baillador dans le forum Langage
    Réponses: 4
    Dernier message: 08/06/2006, 10h14
  4. Réponses: 6
    Dernier message: 17/03/2006, 12h23
  5. Réponses: 2
    Dernier message: 09/02/2006, 18h20

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