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 :

transformer un vecteur<string> en une simple string


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut transformer un vecteur<string> en une simple string
    bonjour à tous,

    Existe t'il un moyen de transformer un vecteur en string ? je m'explique j'ai créer un vecteur contenant chaque element d'une phrase via une fonction split (merci gldivers) , maintenant je tente de créer une fonction qui puisse me selectionner des elements precis de ce vecteur (exemple du 1er au 3eme element) le probleme c'est que pour retourner c'est 3 elements il faut que je les stock dans un string, j'espere que je suis compréhensible

    voici ma fonction qui est censé me retourner des elements precis d'un vecteur:

    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
     
    std::string lrange(const vector<string> &tab, unsigned int begin, unsigned int end)
    {
    	string *src;
    	src = new string[tab.size()];
     
        for (unsigned int i = 0; i < tab.size(); ++i)
        {
    		for (;begin < end; ++begin)
    		{
    			src[begin] = tab[begin];
    		}
    	}
    	return src;
    }
    la seul methode que j'ai trouvé est en utilisant new , dans ce code l'erreur ce situe sur la valeur retourner 'src', le compilateur me dit que je converti un std::string en un non-scalar std::string.
    En fait ma seule et véritable question est dans le titre :p

  2. #2
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    Bah c'est normal qu'il rale, ta fonction est déclarée pour retourner une string alors que toi tu retourne un pointeur.

    Et non tu n'es pas très compréhensible, ce que tu veux faire c'est juste renvoyer un "tableau" contenant seulement certains des éléments de ton vector? et dans ce cas la, autant garder un vector aussi.
    Ou alors c'est retourner une string (donc une seule chaine de caractère), avec les différents bouts accolés les uns aux autres?
    Dans ce cas la pas besoin de new ni de pointeur...

    Après c'est pareil ta boucle semble très douteuse...

  3. #3
    Expert confirmé Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 364
    Points : 5 378
    Points
    5 378
    Par défaut
    Et pourquoi ne pas faire un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    std::string lrange(const vector<string> &tab, unsigned int begin, unsigned int end)
    {
    	string src;
     
        for (unsigned int i = 0; i < tab.size(); ++i)
        {
    		for (;begin < end; ++begin)
    		{
    			src += tab[begin];
    		}
    	}
    	return src;
    }

  4. #4
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    merci a vous deux,
    je vais tenter d'être plus claire j'ai une ligne de ce type:

    configuration4 exemple blabla test crayon sardine papier
    cette ligne je la découpe puis je stock chaque element dans un vecteur,
    dans ce vecteur il se peut que je n'ai besoin que des 3 derniers elements (exemple) d'ou la fonction lrange qui est censé me retourner ces 3 elements, mais il ne me semble pas possible de retourner 3 elements d'un vecteur sans les avoir stocké avant dans un string ... je peux me tromper c'est pour cela que je solicite votre aide, en ce qui concerne la boucle douteuse je ne sais pas si elle fonctionne car je n'ai pas pu tester la fonction lrange du fait que le compilateur grognai après mon sale boulot ...

  5. #5
    Membre confirmé
    Avatar de haraelendil
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2004
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2004
    Messages : 283
    Points : 533
    Points
    533
    Par défaut
    Rien ne t'empêche de retourner un deuxième vector avec uniquement les éléments que tu veux garder...

  6. #6
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    ca me semble être une bonne idée et c'est ce que je vais faire, par contre es-ce que je dois mettre le sujet en résolu ? parceque la question traitée dans le sujet ne l'ai pas.
    En tout cas merci

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Une bonne habitude à prendre est celle qui consiste à ne passer à une fonction que... ce dont elle a réellement besoin.

    Par exemple, une fonction qui voudrait recréer une chaine de caractères "unique" au départ d'une sélection d'éléments issus d'une collection n'a, a priori, besoin que de deux choses: les bornes représentant l'élément de départ et incluant le dernier élément à prendre en compte (donc, s'arrêtant "juste après" le dernier élément à pendre en compte )

    Le problème auquel tu pourrais en effet être confronté n'est pas forcément évident de prime abord:

    Si tu dis explicitement à ta fonction qu'elle doit s'attendre à recevoir un std::vector<std:: string>, et que tu applique la logique adéquate, cela va très bien se passer... tant que tu te retrouvera à vouloir, effectivement travailler avec un std::vector<std:: string>

    Si, pour une raison ou une autre, tu viens à te retrouver non plus avec un vecteur de chaines de caractères, mais bien avec, par exemple, une liste de chaines de caractères (std::list<std:: string> ), ta fonction ne fonctionnera purement et simplement plus, et tu te retrouveras face à la nécessité soit de... remplir un std::vector<std::string> sur base de ta liste, soit à devoir au mieux copier la fonction (qui fera pourtant exactement la même chose), au pire, la modifier en conséquence, en violation flagrante du principe qui demande qu'un code soit ouvert aux évolutions mais fermés aux modifications.

    Nous abordons là un aspect déjà un peu avancé de C++, mais c'est décidément un langage génial, et il serait bête de ne pas profiter de toutes ses possibilités

    En effet, C++ permet l'utilisation du paradigme dit "générique" qui te permet (pour faire simple) de réfléchir en des termes proches de:
    je ne sais pas quel type de donnée je vais manipuler, mais je sais comment je vais les utiliser"
    De plus, C++ présente un concept nommé "itérateur"qui permet de "voyager" entre différents éléments lorsque tu dois les manipuler de manière... itérative.

    On pourrait donc suivre un raisonnement proche de:
    Je ne sais pas d'où viendront les données, mais je sais que j'aurai deux bornes à ma disposition (une sur le premier élément à utiliser, l'autre sur l'élément qui suit le dernier que je dois utiliser), et je vais donc demander de "faire quelque chose" pour chaque élément compris entre ces deux bornes
    Je te fais grâce des réflexions qui mêneront à la création de la logique, mais, au final, tu en arriverais donc à une fonction 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
     
     /* je ne sais pas quel sera le type réel  utilisé" mais, quel qu'il soit, je 
     *dirais qu'il s'appelle emporairement (le temps de l'exécution) iter :D
     */
    template<typename iter>
    std::string lrange(iter begin, // j'ai besoin de la borne de début
                            iter end) // et de la borne de fin 
    {
       /* je pars d'une chaine vide */
       std::string str;
       /* tant que je n'ai pas dépassé le dernier élément que je dois
        * rajouter à ma chaine
        */
       while(begin != end)
       {
           /* je rajoute le contenu de l'élément à ma chaine */
           str+= (*begin);
           /* et je passe à l'élément suivant */
           ++begin;
           /* s'il y a encore un élément à rajouter,
            * j'ajoute un espace pour clairement séparer les différents mots
            */
           if(begin!=end)
               str+=" ";
       }
        /* quand j'arrive ici, j'ai tous les mots, et je peux renvoyer le résultat */
        return str;
    }
    Tu me diras sans doute que cela semble fort proche de ce que l'au aurait pu faire en passant directement des std::vector<std::string>::const_iterator à la fonction, et pourtant...

    Imagine, maintenant, que tu aies:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int main()
    {
        std::string tabC[10]; // un tableau C style de dix chaines
        std::vector<std::string> tabCPP; // un tableau "à la C++"
        std::list<std::string> listeCPP; // et une liste "à la C++"
        // remplissage de tabC, de tabCPP et de listeCPP
        /* comment faire pour récupérer chaque fois une chaine avec 
         * - les éléments de 3 7 inclus de tabC
         * - les éléments compris entre "bonjour" et "world" de tabCpp
         * - l'ensemble des éléments de listeCPP ???
         */
    }
    L'approche "classique" aurait nécessité trois que tu écrives trois versions distinctes de lrange (une pour chaque type de collection envisagé).

    L'approche générique te permet de te contenter d'une seule version, à charge du compilateur de faire le boulot

    La fonction main pourrait donc ressembler à
    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
    int main()
    {
        std::string tabC[10]; // un tableau C style de dix chaines
        std::vector<std::string> tabCPP; // un tableau "à la C++"
        std::list<std::string> listeCPP; // et une liste "à la C++"
        //remplissage de tabC, de tabCPP et de listeCPP
        /* Q :comment faire pour récupérer une chaine avec 
         *  les éléments se trouvant aux indices 3 à 7 inclus de tabC ?
         * R : Simplement en appelant lrange et en passant l'adresse
         * des éléments se trouvant au incides 3 à 8 :
         */
        std::string chaineC=lrange(&tabC[3], &tabC[8]);
     
     
        /* Q : comment faire pour récupérer une chaine avec 
         * les éléments compris entre "bonjour" et "world" de tabCpp
         *  l'ensemble des éléments de listeCPP ?
         * R : en recherchant l'itérateur correspondant à la chaine "bonjour"
         * et un autre à la correspondant ce qui suit la chaine "world" et en les
         * passant à la fonction
         */
        std::vector<std::string>::iterator bVector; // recherche de "bonjour"
        std::vector<std::string >::iterator eVector; // recherche de "world" et
         ++eVector; // passage au suivant
        std::string chaineVector = lrange(bVector,eVector);
        /* Q : comment faire pour récupérer une chaine avec 
         *  l'ensemble des éléments de listeCPP ?
         * R : en transmettant respectivement l'itérateur renvoyé par les 
         * fonctions membres begin et end de la std::list
         */
        std::string chaineListe = lrange(listeCPP.begin(), listeCPP.end());
        return 0;
    }
    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

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Vas-tu découper une chaine en vecteur pour reconstruire une nouvelle chaîne avec des éléments de ce vecteur, nouvelle chaîne que tu vas peut être redécouper pour construire ....... Bref, est-il vraiment pertinent de retourner une nouvelle chaîne ? Ne souhaiterais-tu pas avoir quelque que chose comme un intervalle sur ton premier vecteur (éventuellement avec un filtre) ? En ce cas, il faudrait regarder des choses comme Boost.Range (et boost.iterators probablement).

  9. #9
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Il me semble avoir compris que tu souhaitais passer un conteneur et 2 int représentant les bornes en argument et récupérer un nouveau conteneur contenant les éléments du premier conteneur entre les 2 bornes. Auquel cas, je t'invite à lire les constructeurs des std::vector et tu devrais trouver ce qu'il te faudra (te manquera juste a transformer tes int en iterator).

    Cependant, le paradigme générique peut être très intéressant ici :

    On pourrait faire la même fonction qui prend un conteneur contenant n'importe quel type.

    ta fonction ressemblerait donc a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<typename Conteneur, typename T>
    Conteneur<T> ma_fonction(Conteneur<T> c, unsigned int min, unsigned int max)
    Je te laisse le soin d'écrire le reste...

  10. #10
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Cependant, le paradigme générique peut être très intéressant ici :

    On pourrait faire la même fonction qui prend un conteneur contenant n'importe quel type.
    Ou mieux un range
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  11. #11
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    tout d'abord je tient a tous vous remerciez pour vos reponses et votre aide je vais etudiez toutes vos possibilitées cependant il me semble que je n'ai pas été très clair je vais donc vous détaillez exactement ce que je veux faire, pourquoi et aussi si ca vaut vraiment le coup de faire ainsi.
    Je programme(essaye) un robot pour serveur IRC, une fois le socket connecté le serveur m'envoi des données de ce type:

    192.168.1.3 USER havoc "" "192.168.1.3" :Show yourself
    cette ligne je la stock dans un string, puis il faut que je la traite, donc j'me suis dit pkoi pas la decouper et stocker tout ses éléments dans un vecteur, ensuite pour traiter chaque element j'ai ma fonction lindex qui me permet de retourner un element precis de ce vecteur, cependant dans le cas de la données ci-dessus j'ai besoin de recuperer plusieurs elements qui eux doivent rester intact c'est le cas de la derniere partie:

    192.168.1.3 USER havoc "" "192.168.1.3" :Show yourself
    il s'agit la de deux élément qui doivent être stocké dans un meme string d'ou l'idée de la fonction lrange qui me retourner le nombre d'element dans une plage donné tout en gardant les espaces separateur, j'aurai pu me contenter de ma fonction lindex mais pour ca il faut connaitre le nombre d'element précis de cette partie, puis rajouter manuellement les espaces separateur entre chaques.
    Je ne sais pas si c'est suffisament claire mais de toute façon j'vais pas pouvoir vraiment faire mieux (ma derniere nuit et ma journée passée devant l'ordinateur m'ont completement flingué le cerveau).
    Pour ceux qui m'aurait compris je voudrai aussi avoir votre avis sur ce type de fonction, es-ce qu'elles en vallent vraiment la peine ? ne sont elle pas trop gourmande du fait qu'il est fort possible qu'elle ait a traiter de très grand nombre d'operation en un temps assez cours et ce sur plusieurs jours/mois sans arrêt (si au final mon programme tient la route).

    N'hesitez pas a me demander d'autre précision et encore merci pour votre aide ca me fait vraiment plaisir.

  12. #12
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    j'ai modifié la version lrange de koala, ca a l'air de fonctionner correctement, j'aimerai avoir votre avis , pour le moment je ne me sert de cette fonction que sur des vecteurs donc j'vais attendre un peu avec les templates car deja la j'suis un peu pommé

    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
     
    std::string lrange(const std::vector<string> &tab , unsigned int begin, unsigned int end)
    {
       std::string str;
       end = end + 1; // pour inclure le dernier element
     
       if (end > tab.size()) end = tab.size(); // si end est superieur a la table du vecteur on position end sur son dernier element
       while(begin != end)
       {
           /* je rajoute le contenu de l'élément à ma chaine */
           str+= tab[begin];
           /* et je passe à l'élément suivant */
           ++begin;
           /* s'il y a encore un élément à rajouter,
            * j'ajoute un espace pour clairement séparer les différents mots
            */
           if(begin != end)
               str+=" ";
       }
        /* quand j'arrive ici, j'ai tous les mots, et je peux renvoyer le résultat */
        return str;
    }
    methode d'appel

    string value;
    value = lrange(vecTab, 1, 5);
    me retourne les elements de 1 à 5 inclu du vecteur vecTab
    , pour l'instant cette fonction est bugée je viens de m'en rendre compte ...
    si l'entier end depasse la taille du vecteur la fonction reposistionne automatiquement la position de end sur la taille du tableau, mais si je repositionne end sur la taille du tableau + 1 ca va planter ...
    J'aimerai bien avoir vos avis messieurs

  13. #13
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    1/std::vector<string>::size_type à la place des unsigned int pour les bornes serait plus cohérent.
    2/ if (end > tab.size()) end = tab.size(); j'aurais tendance à l'enlever : à l'appelant de respecter le contrat de ta fonction (cf cette intro à la programmation par contrat).
    3/ Tu dis que tu peux avoir à traiter un grand volume d'information. Ta solution va nécessiter probablement beaucoup d'allocation à chaque sous-chaîne. Est-ce si intéressant de découper en vecteur de string ? Tu pourrais t'appuyer sur un vecteur de std::pair<size_t,size_t> ce qui pourrait aussi être la valeur de retour de lrange (cela suppose pas de trous). Ou carrément ne pas faire de découpe, si les chaînes sont courtes, il faudrait arbitrer entre le temps de parcours d'une string à chaque fois vs le vecteur de tokenisation (mémoire + temps).

  14. #14
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mars 2007
    Messages : 244
    Points : 99
    Points
    99
    Par défaut
    le problème c'est que si je ne vérifie pas que le dernier element demandé n'est pas supèrieur a la table du tableau j'ai une erreur de segmentation j'vois pas comment faire autrement, sinon oui il aura beaucoup d'information a traiter mais comment faire autrement car il faut que je traite cette chaine donc forcement que je le découpe , mes fonctions lindex et lrange m'aident bien pour ca mais c'est vrai que si elles sont trop gourmande ca n'en vaut pas la peine mais comment faire autrement ? comment feriez vous a ma place ? en perl j'avais pas ce soucis les expressions régulières me mâchaient le boulot la je ne vois pas comment faire court, fiable et peu gourmand, j'ai besoin de vos conseil de pro !

  15. #15
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par havoc50 Voir le message
    en perl j'avais pas ce soucis les expressions régulières me mâchaient le boulot la je ne vois pas comment faire court, fiable et peu gourmand, j'ai besoin de vos conseil de pro !
    Boost::regexp ou Boost:: xpressive

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Goten Voir le message
    Ou mieux un range
    Tu remarquera que c'est ce que j'ai proposé un peu plus haut
    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

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par havoc50 Voir le message
    j'ai modifié la version lrange de koala, ca a l'air de fonctionner correctement, j'aimerai avoir votre avis , pour le moment je ne me sert de cette fonction que sur des vecteurs donc j'vais attendre un peu avec les templates car deja la j'suis un peu pommé

    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
     
    std::string lrange(const std::vector<string> &tab , unsigned int begin, unsigned int end)
    {
       std::string str;
       end = end + 1; // pour inclure le dernier element
     
       if (end > tab.size()) end = tab.size(); // si end est superieur a la table du vecteur on position end sur son dernier element
       while(begin != end)
       {
           /* je rajoute le contenu de l'élément à ma chaine */
           str+= tab[begin];
           /* et je passe à l'élément suivant */
           ++begin;
           /* s'il y a encore un élément à rajouter,
            * j'ajoute un espace pour clairement séparer les différents mots
            */
           if(begin != end)
               str+=" ";
       }
        /* quand j'arrive ici, j'ai tous les mots, et je peux renvoyer le résultat */
        return str;
    }
    methode d'appel



    me retourne les elements de 1 à 5 inclu du vecteur vecTab
    , pour l'instant cette fonction est bugée je viens de m'en rendre compte ...
    si l'entier end depasse la taille du vecteur la fonction reposistionne automatiquement la position de end sur la taille du tableau, mais si je repositionne end sur la taille du tableau + 1 ca va planter ...
    J'aimerai bien avoir vos avis messieurs
    Mais pourquoi passer par le vecteur en paramètre

    Passe directement les deux bornes, et donc un itérateur sur le premier élément à gérer et un autre sur... ce qui suit le dernier.

    Il y a, de toutes façons beaucoup de chances que tu doive rechercher les indices ou les bornes que tu veux utiliser:

    L'appel se fera beaucoup plus souvent sous un forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    size_t begin;
    size_t end
    /* recherche de l'indice du premier élément, ou d'un itérateur sur celui-ci 
     * et recherche équivalente sur le dernier élément
     */
    std::string result= lrange(vecteur,begin, end);
    vu que l'utilisation d'indices codés en dur impliquerait que tu sache précisément ce qui se trouve dans ton vecteur de chaines.

    De plus, n'oublie pas que "qui peut le plus peut le moins"...

    j'avais donné un exemple d'appel sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string chaineVector = lrange(bVector,eVector);
    de ma version, mais elle permet également une forme d'appel sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string str=lragne(&vecteur[3], &vecteur[8]);
    pour prendre les valeurs se trouvant aux indice 3 à 7 inclus.

    Tu as littéralement tout à gagner, quand tu es en mesure de déterminer un comportement qui restera valable en toutes occasions, à travailler sous une forme générique, car cela te permet d'acquérir une souplesse incroyable au moment de l'appel en s'adaptant "natuellement" aux différentes situations dans lesquelles tu pourra te trouver, sans nécessiter de ta part la moindre ligne de code supplémentaire.

    Si tu as, par exemple, une classe qui manipule une collection de std::string (par exemple, car ca pourrait être de n'importe quoi d'autre), tu peux estimer utile de permettre de créer une instance de ta classe dans laquelle la collection est vide par défaut, mais tu peux aussi vouloir permettre à l'utilisateur de... remplir cette collection au moment où il crée l'instance de la classe.

    Mais, dans ce cas là, il ne sert pas à grand chose de vouloir limiter les possibilités de remplissage à la seule collection effectivement utilisée en interne (car l'utilisateur de la classe n'a aucun besoin de savoir laquelle est utilisée).

    Tu aurais donc, au final, une classe 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
    class MaClass
    {
        /* ca, c'est pour mon usage interne */
        typedef std::vector<std::string> vector;
        public:
             /* j'incite l'utilisateur à utilise MaClass::iterator et 
              * MaClass::const_iterator pour le cas où je déciderais un
              * jour d'utiliser std::list plutôt que std::vector
              */
            /* un constructeur qui garde la collection vide */
            MaClass(){}
            /* Je permet à l'utilisateur de remplir diretement la collection
             * en le laissant libre de choisir n'importe quelle source d'origine
             * tout ce qu'il a à faire, c'est me donner les deux borne (le range)
             */
            template<typename it>
            MaClass(it b, it e):items_(b,e){}
            /* je permet (si cela a un sens) à l'utilisateur d'avoir un iterateur
             * "simple" sur le premier élément de la collection et un autre
             * sur le dernier
             */
            iterator begin(){return items_.begin();}
            iterator end(){return items_.end();}
            /* et je fais pareil avec des itérateurs constants */
            const_iterator begin() const{return items_.begin();}
            const_iterator end() const{return items_.end();}
            /* d'autres trucs sympa éventuels */
        private:
            /* la collection qui est utilisée en interne */
            vector items_;
    };
    Au final, tout ce que l'utilisateur doit savoir, c'est qu'il dispose de deux solution pour créer une instance de MaClass:
    1. Soit il laisse la collection de chaines vides (il utilise pour cela le constructeur par défaut)
    2. Soit il fournit deux bornes représentant l'ensemble des chaines qu'il veut ajouter directement

    Maintenant, qu'il décide de le faire sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main()
    {
        char tab[5][]={"salut","bonjour","hello","world","monde"};
        MaClass obj(tab[0],tab[5]);
    }
    ou sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
        std::vetor<std::string> tab;
        /* remplissage de tab */
        MaClass obj(tab.begin(),tab.end();
        /* voir même
         * MaClass obj(&tab[0], & tab[tab.size()]);
    }
    ou encore sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
        std::list<std::string> list;
        /* remplissage de la liste */
        MaClass obj(list.begin(), list.end());
    }
    ou, enfin sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
        std::set<std::string> s;
        /* remplissage du set */
        MaClass obj(s.begin(),s.end());
    }
    n'aura strictement aucune importance: tu laisse à l'utilisateur le choix de la manière de faire, et cela lui laisse donc d'autant plus de possibilités de s'adapter aux situations particulières qu'il peut rencontrer.

    Le code que je donnais plus haut suit exactement le même principe: ce n'est pas à toi de placer des restrictions inutiles sur l'usage qui peut être fait d'une fonction .
    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. Réponses: 4
    Dernier message: 27/04/2013, 22h15
  2. Mettre le contenu d'une variable String dans un tableau de String
    Par patriot dans le forum Collection et Stream
    Réponses: 14
    Dernier message: 31/05/2011, 15h25
  3. [String] Remplir un tableau de String à partir d'une boucle "for"
    Par dev197 dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 12/08/2009, 15h29
  4. Impossible d'imprimer une simple String!
    Par nicdo77 dans le forum Langage
    Réponses: 14
    Dernier message: 18/01/2008, 14h57
  5. Réponses: 2
    Dernier message: 10/04/2007, 12h39

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