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

SL & STL C++ Discussion :

Les nombres dans des std::string


Sujet :

SL & STL C++

  1. #21
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Ok, merci merci merci.
    Je n'ai donc pas tout à fait tort, sauf peut-être en ce qui concerne le timing: les optimizations se font, éventuellement, en dernier ressort et seulement là où c'est utile.

    D'un point de vue strictement technique, j'aimerais savoir si la manière d'utiliser std::string dans l'extrait de code suivant est correcte, universelle et dépourvue d'effets de bord (en fonction du compilo, etc) le but étant d'accéder en écriture au contenu d'un std::string.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    std::string s;
    s.resize(bufp-buf);
    std::string::iterator it_s=s.begin();
    while (bufp!=buf)
    {
    	char c=*--bufp;
    	*it_s=(char)(c+'0');
    	++it_s;
    }
    return s;

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par camboui Voir le message
    Ok, merci merci merci.
    Je n'ai donc pas tout à fait tort, sauf peut-être en ce qui concerne le timing: les optimizations se font, éventuellement, en dernier ressort et seulement là où c'est utile.
    C'est l'idée générale

    D'autant plus que:
    1. La S(T)L est malgré tout relativement optimisée
    2. Le compilateur est souvent en mesure de faire des optimisations bien meilleures que toi, si tu lui permet de comprendre le contexte
    3. Les optimisation qui se basent sur les effets de bord et autres "sucres syntaxiques" sont généralement très gourmandes en temps de conception, de mise au point, de débuggage et de modification

    Il ne sert donc pas à grand chose, si la logique et la conception sont bonnnes, de commencer à perdre du temps à chercher à optimiser des écritures, ou à chercher des méthodes plus complexes que la méthode "la plus simple" si c'est pour gagner trois cycle d'horloge sur une fonction qui n'est appelée qu' exceptionnellement
    D'un point de vue strictement technique, j'aimerais savoir si la manière d'utiliser std::string dans l'extrait de code suivant est correcte, universelle et dépourvue d'effets de bord (en fonction du compilo, etc) le but étant d'accéder en écriture au contenu d'un std::string.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    std::string s;
    s.resize(bufp-buf);
    std::string::iterator it_s=s.begin();
    while (bufp!=buf)
    {
    	char c=*--bufp;
    	*it_s=(char)(c+'0');
    	++it_s;
    }
    return s;
    Tu as un effet de bord à la ligne : char c=*--bufp;
    En effet, tu modifie d'un côté l'adresse pointée par un pointeur, et de l'autre, tu assigne ce qui est pointé par ce pointeur à un caractère

    Le risque encouru est qu'une lecture rapide du code fasse que le lecteur "zappe" la décrémentation

    Or, cela revient strictement au même que le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char c = *bufp;
    --bufp;
    qui montre bien toutes les étapes

    Pour répondre à ta question de savoir si c'est correct, je dirais qu'il faut se mettre d'accord sur le terme "correct" (par exemple: tu obtiens une chaine inversée par rapport au buffer d'origine, est ce ce que tu souhaite ).

    Quant à savoir si c'est universel et indépendant du compilo, je dirais que c'est effectivement le cas, vu que tu n'utilise que des types primitifs ou des classes fournie par le standard

  3. #23
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Quant à savoir si c'est universel et indépendant du compilo, je dirais que c'est effectivement le cas, vu que tu n'utilise que des types primitifs ou des classes fournie par le standard
    Ça n'a rien d'une règle générale... Le code suivant n'utilise que des types standards, mais son résultat dépend du compilateur...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main()
    {
    	char c=-1;
    	assert(c/2 == 127);
    }

    Dans le cas en question, le c+'0' peut donner des résultats variables en fonction du compilateur, et de la plage de valeur de c.

  4. #24
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    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 ul2string(unsigned long value)
    {
    char buf[12];
    char *bufp=buf;
    for(;;)
    {
    	*bufp++=(char)(value % 10u);
    	if ((value/=10u)==0ul)
    		break;
    }
    std::string s;
    s.resize(bufp-buf);
    std::string::iterator it_s=s.begin();
    while (bufp!=buf)
    {
    	char c=*--bufp;
    	*it_s=(char)(c+'0');
    	++it_s;
    }
    return s;
    }
    D'un point de vue strictement technique, j'aimerais savoir si la manière d'utiliser std::string dans l'extrait de code suivant est correcte, universelle et dépourvue d'effets de bord
    Je pense que oui. Le plus rapide et le plus sur pour l'accès direct à la string, c'est en effet son itérateur.

    Il faut juste garder en tête en bossant directement avec les itérateurs que toute modification de la taille de la string peut les invalider. Par exemple, avec visual 2008 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::string s;
    std::string::iterator it = s.begin();
    s.resize(5);
    *it = 'a'; // OK
    s.resize(100);
    *it = 'a'; // BOUM, itérateur invalide
    Dans ce cas, je crois que ça vient du fait que VS alloue les string sur la pile tant qu'elles sont assez légères puis passe sur le tas à partir d'une certaine taille.

  5. #25
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par koala01 Voir le message
    ...
    Tu as un effet de bord à la ligne : char c=*--bufp;
    En effet, tu modifie d'un côté l'adresse pointée par un pointeur, et de l'autre, tu assigne ce qui est pointé par ce pointeur à un caractère

    Le risque encouru est qu'une lecture rapide du code fasse que le lecteur "zappe" la décrémentation

    Or, cela revient strictement au même que le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char c = *bufp;
    --bufp;
    qui montre bien toutes les étapes
    Arf... C'est la deuxième fois que je te reprends
    Tu veux dire je suppose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    --bufp;
    char c = *bufp;
    *--bufp et *bufp-- c'est pas tout à fait la même chose...
    Décidément tu n'aimes pas ma manière compact d'écrire du code. Je ne l'ai pas inventé, c'est du C parfaitement valide (et c'était prévu exprès). Je suppose que c'est une habitude qui vient depuis l'époque où (il y a bien longtemps) on nous disait qu'il fallait "aider" le compilo dans ses optimizations.
    Je me rappelle d'ailleurs que d'autres en ces temps reculés avaient déjà souligné le manque de lisibilité du code C ainsi compacté, autres à qui on avait finalement rétorqué qu'un bon programmmeur devait pouvoir s'adapter à lire du code ayant pu être écrit par quiconque.

    A propos de "correct", je parlais de la manière d'utiliser std::string, en particulier l'accès à son contenu.
    Citation Envoyé par koala01 Voir le message
    Pour répondre à ta question de savoir si c'est correct, je dirais qu'il faut se mettre d'accord sur le terme "correct" (par exemple: tu obtiens une chaine inversée par rapport au buffer d'origine, est ce ce que tu souhaite ).

    Quant à savoir si c'est universel et indépendant du compilo, je dirais que c'est effectivement le cas, vu que tu n'utilise que des types primitifs ou des classes fournie par le standard
    Mais Aznar a répondu dans le sens que je supposais/voulais
    Merci !

  6. #26
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::string s;
    std::string::iterator it = s.begin();
    s.resize(5);
    *it = 'a'; // OK
    s.resize(100);
    *it = 'a'; // BOUM, itérateur invalide
    Perso, je ne ferais jamais ça (assigné un iterator avant un resize). Mais plutôt ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::string s;
    s.resize(5);
    std::string::iterator it = s.begin();
    *it = 'a'; // OK
    s.resize(100);
    it = s.begin();
    *it = 'a'; // plus BOUM, itérateur valide
    Et c'est valable pour tous les itérateurs de la STL en général dès que le taille d'un conteneur est susceptible d'avoir changé.
    C'est d'ailleurs une des difficulté de la STL il me semble, connaitre la durée de vie ou la validité d'un itérateur.

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

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par camboui Voir le message

    Je me rappelle d'ailleurs que d'autres en ces temps reculés avaient déjà souligné le manque de lisibilité du code C ainsi compacté, autres à qui on avait finalement rétorqué qu'un bon programmmeur devait pouvoir s'adapter à lire du code ayant pu être écrit par quiconque.
    Oui mais justement le C++ n'est pas du C.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par camboui Voir le message
    Arf... C'est la deuxième fois que je te reprends
    Tu veux dire je suppose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    --bufp;
    char c = *bufp;
    *--bufp et *bufp-- c'est pas tout à fait la même chose...
    Décidément tu n'aimes pas ma manière compact d'écrire du code. Je ne l'ai pas inventé, c'est du C parfaitement valide (et c'était prévu exprès). Je suppose que c'est une habitude qui vient depuis l'époque où (il y a bien longtemps) on nous disait qu'il fallait "aider" le compilo dans ses optimizations.
    Je me rappelle d'ailleurs que d'autres en ces temps reculés avaient déjà souligné le manque de lisibilité du code C ainsi compacté, autres à qui on avait finalement rétorqué qu'un bon programmmeur devait pouvoir s'adapter à lire du code ayant pu être écrit par quiconque.
    Effectivement, je ne nierai pas que j'ai horreur des sucres syntaxiques

    Ceci dit, il faut bien te dire que les compilo un tant soit peu récents (mettons simplement ceux sorti depuis la norme C99), ont fait d'énormes progrès en ce qui concerne les optimisations qu'ils sont capables d'apporter...

    Ce qui pouvait être vrai il y a une vingtaine d'années (ou plus) ne l'est donc plus maintenant, et c'est tout bénéfice en ce qui concerne les périodes de débuggage et de mise au point

    En outre, il faut effectivement se méfier de ce "Et c'est du C valide" car, bien que le C++ hérite du C, on remarque que, les normes évoluant de manière séparée, il est des choses qui sont valides en C mais pas en C++, voire, des fonctions dont il faut adapter l'invocation pour passer de l'un à l'autre (le coup de malloc est assez parlant sur le sujet )

  9. #29
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Dans ce cas, je crois que ça vient du fait que VS alloue les string sur la pile tant qu'elles sont assez légères puis passe sur le tas à partir d'une certaine taille.
    Euh... Là tu racontes n'importe quoi. Les caractères qui composent une string sont toujours stockées sur le tas. Par contre l'objet string peut être soit sur la pile soit sur le tas.

  10. #30
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Non, je crois bien que arzar a raison. Depuis VS2003 std::string n'alloue sur le tas qu'à partir d'une certaine taille.
    D'ailleurs, depuis que je fréquente ce forum () on me fait comprendre que je ne dois pas faire de supposition sur ce que fait ou pas un compilo avec les std::string. On ne doit même pas supposer que la string occupe toujours un espace contigu en mémoire, seul l'appel après c_str() ou data() le garantit.

  11. #31
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par camboui Voir le message
    Non, je crois bien que arzar a raison. Depuis VS2003 std::string n'alloue sur le tas qu'à partir d'une certaine taille.
    D'ailleurs, depuis que je fréquente ce forum () on me fait comprendre que je ne dois pas faire de supposition sur ce que fait ou pas un compilo avec les std::string. On ne doit même pas supposer que la string occupe toujours un espace contigu en mémoire, seul l'appel après c_str() ou data() le garantit.
    Dans ce cas cela signifie que la classe std::string de Visual doit avoir un membre du genre char[...]. Mais bon du coup la taille d'un objet doit être "énorme".

    PS: Toutes mes excuses à Arzar pour avoir été un peu "sec".

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par camboui Voir le message
    Non, je crois bien que arzar a raison. Depuis VS2003 std::string n'alloue sur le tas qu'à partir d'une certaine taille.
    D'ailleurs, depuis que je fréquente ce forum () on me fait comprendre que je ne dois pas faire de supposition sur ce que fait ou pas un compilo avec les std::string. On ne doit même pas supposer que la string occupe toujours un espace contigu en mémoire, seul l'appel après c_str() ou data() le garantit.
    De manière générale, il ne faut faire aucune supposition sur la manière dont n'importe quel compilateur implémente quoi que ce soit si ce n'est pas explicitement précisé dans la norme...

    Et même pour ce qui est explicitement précisé dans la norme, en étant - il faut l'avouer - un tout petit peu paranoïaque, il y a encore lieu de vérifier si le compilateur utilisé (quel qu'il soit encore une fois) la respecte avant de partir du principe que c'est un fait acquis

    En effet, il reste malgré tout relativement rare de trouver un compilateur qui présente une implémentation respectant l'intégralité de la norme, qui - rappelons le - prend malgré tout la forme d'un bouquin de plus de 700 pages, réparties en 27 sections et 5 annexes, et dont il est malgré tout relativement difficile d'avoir une vue d'ensemble... (et je ne parle encore ici que de la norme de 2003 )

    A l'heure actuelle, si l'on peut considérer que la grosse majorité des compilateurs ont fini par implémenter de manière correcte les prescriptions relatives aux principes importants de la norme (même borland semble avoir fait un sérieux effort sur le sujet), il n'est malgré tout pas impossible de rencontrer des parties plus complexes de la norme pour lesquelles un ou l'autre compilateur risque d'éprouver des difficultés à suivre les prescriptions

    Et, si l'on considère enfin qu'il y a des comportements dont l'implémentation est soit laissée à l'appréciation de l'éditeur du compilateur, soit purement et simplement non définis dans la norme, cela laisse encore beaucoup de place à l'interprétation personnelle

  13. #33
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Montag Voir le message
    Dans ce cas cela signifie que la classe std::string de Visual doit avoir un membre du genre char[...]. Mais bon du coup la taille d'un objet doit être "énorme".
    L'idée est de pirater les autres membres de la string (comme le pointeur sur les caractères) pour y stocker directement les caractères quand il y en a peu. Ca se nomme en général "small string optimisation".

  14. #34
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Une sorte de "union" quoi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    union
    {
     char s[...];
     struct
     {
      char *ptr;
      size_t len;
      ...
     };
    };

  15. #35
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Dans le mille !
    En cherchant "union" dans l'implémentation de la stl de mircrosoft (fichier xstring) on trouve ceci :

    (_Elem est un typedef vers char pour les std::string et wchar pour les std::wstring)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    union _Bxty
       {	//  storage for small buffer or pointer to larger one
       _Elem _Buf[_BUF_SIZE];  
       _Elem *_Ptr;
    } _Bx;
     
    // Avec un peu avant
     
    enum
       {	// length of internal buffer, [1, 16]
        _BUF_SIZE = 16 / sizeof (_Elem) < 1 ? 1
         : 16 / sizeof(_Elem)};
    Ben c'est sacrement malin quand même.

  16. #36
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,
    je remonte cette discussion après avoir découvert des choses très intéressantes sur "les nombres dans std::string", lors de mon apnée quotidienne dans le draft du nouveau standart pour le C++0x.
    Behold !
    Citation Envoyé par Draft standart C++0x
    Chapitre 21.4 Numeric conversion
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int stoi(const string& str, size_t *idx = 0, int base = 10);
    long stol(const string& str, size_t *idx = 0, int base = 10);
    unsigned long stoul(const string& str, size_t *idx = 0, int base = 10);
    long long stoll(const string& str, size_t *idx = 0, int base = 10);
    unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);
    1. Effects: the first two functions call strtol(str.c_str(), ptr, base), , and the last three functions call strtoul(str.c_str(), ptr, base), strtoll(str.c_str(), ptr, base), and strtoull(str.c_str(), ptr, base), respectively. Each function returns the converted result, if any. The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx. If the function does not throw an exception and idx != 0, the function stores in *idx the index of the first unconverted element of str.
    2. Returns: the converted result.
    3. Throws: invalid_argument if strtol, strtoul, strtoll, or strtoull reports that no conversion could be performed. Throws out_of_range if the converted value is outside the range of representable values for the return type.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float stof(const string& str, size_t *idx = 0);
    double stod(const string& str, size_t *idx = 0);
    long double stold(const string& str, size_t *idx = 0);
    [Effect, return, throw...]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    string to_string(long long val);
    string to_string(unsigned long long val);
    string to_string(long double val);
    1. Returns: each function returns a string object holding the character representation of the value of its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of "%lld", "%llu", or "%Lf", respectively., where buf designates an internal character buffer of sufficient
    2. Throws: nothing

    [Même ensemble de fonctions, avec des wstring]
    Hourra!!
    Enfin une forme claire, efficace et lisible pour l'extraction d'un nombre. On n'aura plus à rougir en expliquant qu'il faut utiliser stringstream pour une tache aussi simple.

    Deux questions qui me viennent :
    1) Pourquoi seulement trois surcharges pour la fonction to_string ? Je suppose que l'idée est de tirer parti d'une conversion implicite vers le type le plus large, mais il est un peu dommage de devoir convertir un innocent float en long double, juste pour avoir un peu moins de fonctions à implémenter, non ?
    2) Pourquoi ne pas fournir une version générique dans la foulée ? L'implémentation ne me semble pas très complexe (à part la gestion d'erreur ) et le résultat pourrait être assez élégant, dans la lignée de boost::lexical_cast<>.
    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
     
    template <typename T>
    T from_string(const string& s)
    {
       std::istringstream iss(s); // c++0x istringstream peut prendre une const string& dans le constructeur 
       T result;
       iss >> result;
       return result;
    }
     
    template <>
    float from_string(const string& s)
    {
       return stof(s);
    }
     
    ...
    std::string s2 = "3.1415";
    float pi = string_to<float>(s2); // appelle stof
    Ne resterait plus qu'à trouver un nom générique catchy. Je propose :
    T vers string :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string to_string<T>(T); // risque de collision ?
    string vers T :
    Bon là, ça se corse, pourquoi pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    T sto<T>(const string&); // imite les stoi,stof etc.
    T string_to<T>(const string&); // plus explicite, reflet de to_string.
    T from_string<T>(const string&); // symétrie to_string / from_string
    T extract<T>(const string&); // pas mal aussi.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    A vrai dire, stoi, stoul, stol et consort existent déjà...

    Le problème est que cela t'oblige à connaitre autant de fonction qu'il n'y a de type, ou peu s'en faut.

    C'est là que les stringstream entrent en jeu: un méthode unique permet de travailler avec n'importe quoi, y compris avec des types personnalisés, ce que ne permettent pas les fonctions "classiques".

    De ce point de vue, le draft de C++0x ne change, sauf erreur, pas énormément

  18. #38
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A vrai dire, stoi, stoul, stol et consort existent déjà...

    Le problème est que cela t'oblige à connaitre autant de fonction qu'il n'y a de type, ou peu s'en faut.

    C'est là que les stringstream entrent en jeu: un méthode unique permet de travailler avec n'importe quoi, y compris avec des types personnalisés, ce que ne permettent pas les fonctions "classiques".

    De ce point de vue, le draft de C++0x ne change, sauf erreur, pas énormément
    Alors là je râle un peu. Si tu savais que ça existait depuis le début, pourquoi ne pas l'avoir dit plus tôt ?
    Je ne trouve pas très - comment dire ? - "pédagogique" de nous embarquer dans les stringstream quand on en a fait le tour, constaté que c'était lourdingue, et qu'on demande explicitement mieux. En ce qui me concerne en tout cas, j'ai un peu dépassé le stade d'afficher des "coucou 523, bonjour 1234.5, hello world" sur la console.
    Je vais vérifier dès demain ce que propose le compilo (et à propos, c'est dans quel header #include ?)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par camboui Voir le message
    Alors là je râle un peu. Si tu savais que ça existait depuis le début, pourquoi ne pas l'avoir dit plus tôt ?
    Je ne trouve pas très - comment dire ? - "pédagogique" de nous embarquer dans les stringstream quand on en a fait le tour, constaté que c'était lourdingue, et qu'on demande explicitement mieux. En ce qui me concerne en tout cas, j'ai un peu dépassé le stade d'afficher des "coucou 523, bonjour 1234.5, hello world" sur la console.
    Je vais vérifier dès demain ce que propose le compilo (et à propos, c'est dans quel header #include ?)
    Alors, c'est que tu n'a décidément rien compris de ce que l'on essaye de te faire comprendre, à savoir:
    1. avant de t'inquiéter d'essayer d'optimiser - en utilisant ta propre méthode - un comportement quelconque, tu dois veiller à optimiser l'algorithme qui l'utilise: les gains en performances seront bien plus importants (il n'y a qu'une fois que tu as la certitude (pour autant qu'on puisse l'avoir) que tu as le meilleur algorithme, et uniquement si tu te rend compte que le comportement en question occasionne un goulot d'étranglement qu'il devient intéressant d'envisager l'optimisation du comportement "standard")
    2. Un code est sans doute lu plus de cinq fois plus souvent qu'il n'est écrit ou modifié et compilé: la première qualité que l'on demande donc à un code, je dirais presque avant même de respecter l'algorithme et de faire ce qu'on attend de lui, c'est d'être facilement lisible et compréhensible... Outre le fait que les stringstream permettent de convertir n'importe quoi en chaine et inversément, ils présentent en outre l'énorme avantage de présenter une interface sensiblement identique à tout ce qui a trait à la gestion des flux, et donc à permettre bien plus facilement de faire le rapprochement quant au travail effectué
    3. stoul et consort utilisent des chaines de caractères "C style" dans toute leur splendeur, et bien qu'il est très facile de convertir une std::string en chaine "C style" et inversément, il n'y a pas vraiment de raison de décider de le faire "juste pour le plaisir": Autant utiliser tout ce qui permet de manipuler directement les std::string... Que cela passe par l'utilisation de chaines "C style" et des fonction sto*, ce n'est pour toi qu'un détail d'implémentation, et tu n'a (pour ainsi dire) pas à t'en occuper
    4. Il faut impérativement se méfier des observations personnelles quant à la représentation qui peuvent être fait des types primitifs... La norme laisse beaucoup trop de liberté aux créateur de compilateurs pour pouvoir partir d'une autre règle que 1 = char <= short <= int <= long <= long long + (unsigned) int = taille suffisante pour représenter l'ensemble des adresses mémoire disponibles: toute autre hypothèse, entre autre basée sur tes observations perso, sur ta machine et avec ton compilateur perso, tend à préparer le moment où tu foncera dans le mur si les conditions (de machine et ou de compilateur) viennent à changer
    5. Les méthodes issues du C++ sont - de manière quasi systématique - en tut cas bien plus sécurisantes que l'utilisation des méthodes issues du C équivalentes... Or stol et consort font justement partie... de ces méthodes issues du C
    C'est arguments sont débattus en long, en large et en travers sur le forum, aussi je peux t'assurer que ce sont des points qu'il est vraiment intéressant de garder en tête en permanence (même s'ils sont dans une forme fortement résumée dans cette intervention)

    Une fois que tu as admis ces quelques points, il devient difficile de dire qu'on est lourd à venir parler en priorité des stringstream's

    Maintenat, si tu n'est pas d'accord avec l'un de ces arguments, n'hésite pas à te faire entendre: on peut le justifier de bien des manières

  20. #40
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Je crois que tu entretiens un petit malentendu. Qui parle de C-style ?
    J'ai réagi à ta réponse à Arzar, réponse que je trouvais un peu condescendante. Arzar parle de C++0x, de nouvelles fonctions qui vont faire partie du C++, des fonctions permettant la conversion directe entre std::string et nombre (ou alors je n'ai pas compris son intervention).
    C'est ce que je cherchais depuis le début. Je constate que je ne suis pas le seul à se soucier de ce "manque" puisque les gourous du C++ se proposent d'intégrer enfin ce genre de fonction somme toute élémentaire.

    Certes ton discours théorique est juste, quoique académique.
    Mais il s'agit ici de partage de connaissance: existe-t-il, oui ou non, des fonctions C++ pour la conversion directe de std::string en nombre et vice & versa ? La réponse semble être "non", pas encore, mais ça va bientôt être "oui".
    Il semblait que tu disais à Arzar "je le savais mais je ne voulais pas le dire". Je me trompe peut-être, à toi de confirmer ou infirmer.
    Ça me rappelle un peu mon prof d'algorythmique en fac, on y avait vu en détail le tri par tas (heapsort), d'autres algos avaient simplement été mentionnés. A l'examen, celui qui lui écrivait l'algo du quicksort au tableau était busé...
    Au boulot, c'est celui qui n'utilise pas quicksort qui est busé.
    Tu es un peu comme le prof, tu imposes les "stringstream" par principe autoritaire, pas par efficacité.

    En ce qui me concerne, j'ai passé plus de temps à lire et essayer de comprendre les tenants et aboutissant des stream qu'à écrire ma petite fonction qui convertit les std::string en nombre. Et je n'ai pas encore fini l'apprentissage des stream (ils sont assez/trop complexes je trouve). J'ai posé la question autour de moi (des collègues), personne n'utilise ces "machins" (sauf pour faire du log en console). Dur dur de bénéficier de l'expérience de tiers. Donc, en théorie je suis sensé gagner du temps avec les stringstream. En pratique j'en perds...
    Certes, on fait beaucoup d'autres choses avec les stream. Et justement, ça ne plait pas, ça ne convient pas et je pense que je vais faire comme beaucoup, ne pas les utiliser finalement.

    Si un jour on me pose la question que je posais au début de cette discussion, je donnerais les réponses que je connais. Je n'imposerais pas "la" solution C++ qui consiste à passer par l'intermédiaire des stringstream.
    Ainsi, j'ai écrit des fonctions de conversions d'entiers (signé ou non) de et vers les std::string. C'est fait, parce que c'était mon plaisir de le faire, parce que je n'utilise pas le C++ uniquement comme un langage de 4ème ou 5ème génération, parce que finalement c'est simple à faire et qu'on ne perd pas de temps en le faisant. Si quelqu'un veut mon code il suffit de demander. Il devrait être "portable".

    En réaction à ton point 2, je crois bien que personne ne lit mon code, pas plus que je ne lis celui des mes collègues. Est-ce une médiocrité spécifique aux gestionnaires de ma boîte de ne pas prévoir la communication et l'échange internes, où est-ce généralisé ?

    Je voudrais aussi réagir à ton point 1, mais il y a trop à dire. En substance il n'y a pas qu'une "optimisation" qui intervient éventuellement à la fin du développement. Il y en a plusieurs et elles interviennent à tout moment tout au long du développement. Et la première est d'anticiper dès la conception du projet où seront les goulots d'étranglement.
    Bien sûr, ma misérable conversion string/nombre n'aura aucune incidence mesurable sur les performances. Mais il est bon de prendre ce que je pense être une bonne habitude: choisir le meilleur si c'est sans compromis. Et pour moi le meilleur estet non pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    stringstream ss;
    ss << i;
    string s=s.str();
    C'est mon avis: le premier code est plus lisible, il est plus performant, et il est plus rapide à taper. J'accepte que tu ne sois pas d'accord, mais laisse-moi le choix.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Réponses: 7
    Dernier message: 01/09/2006, 14h19
  2. [XSD] : Garder les espaces dans un champ string
    Par cvacavant dans le forum Valider
    Réponses: 8
    Dernier message: 10/02/2006, 09h28
  3. Optimiser les jointures dans des requêtes
    Par klereth dans le forum PostgreSQL
    Réponses: 12
    Dernier message: 23/04/2005, 17h29
  4. [langage] probleme avec les listes dans des listes
    Par pqmoltonel dans le forum Langage
    Réponses: 7
    Dernier message: 27/04/2004, 12h32
  5. Trouver les redirections dans des traces
    Par severine dans le forum Développement
    Réponses: 3
    Dernier message: 21/04/2004, 18h51

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