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 :

problème de setfill() sur wide stringstream


Sujet :

C++

  1. #1
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut problème de setfill() sur wide stringstream
    Bonjour,

    J'essaye de formatter un nombre sur 4 caractères et complété avec des 0 à droite
    2 ==> "0002"
    Le code que j'ai, c'est cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::stringstream str;
    str << std::setw(4) << std::setfill('0') << 2;
    et cela marche très bien. Par contre, j'essaie de faire la même chose avec un string wide char
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::wstringstream str;
    str << std::setw(4) << std::setfill('0') << 2;
    Et là, je me fait jeter à la compilation à cause du setfill(). Qu'est ce que je fait mal et comment dois je m'y prendre ?
    error C2679: '<<' binaire*: aucun opérateur trouvé qui accepte un opérande de partie droite de type 'std::_Fillobj<_Elem>' (ou il n'existe pas de conversion acceptable)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  2. #2
    Membre expérimenté
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    181
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 181
    Par défaut
    Le problème est sur le setfill : les wstring utilisent des wchar_t alors que le caractère de remplissage utilisé est de type char.
    Tu peux simplement utiliser le préfixe L pour indiquer que le littéral est un wchar_t :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::wstringstream str;
    str << std::setw(4) << std::setfill(L'0') << 2;

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Merci pour la réponse, c'est effectivement cela

    Je viens de faire un petit test pour mesurer la différence de vitesse entre le std::streamstring C++ et le sprintf() C
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    #include <stdio.h>
    #include <io.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <fstream>
    #include <windows.h>
    #include <iostream>
    #include <sstream>
    #include <iomanip>
     
    DWORD _chrono = 0;
    void _start_chrono(void)
    {
    	_chrono = GetTickCount();
    }
     
    void _display_chrono(const char * Message)
    {
    DWORD diff = GetTickCount() - _chrono;
    	printf("%s : Elapsed time is %.2f s\n", Message, (double)diff / 1000);
    }
     
    void _test_write_string_stream(const unsigned long Nb1, const unsigned long Nb2)
    {
    	for(int boucle1 = 0; boucle1 != Nb1; boucle1++)
    	{
    		for(int boucle2 = 0; boucle2 != Nb2; boucle2++)
    		{
    			std::wstringstream str;
    			str
    				<< std::setw(5) << std::setfill(L'0') << boucle1
    				<< L", "
    				<< std::setw(5) << std::setfill(L'0') << boucle2
    				<< L"\n"
    				;
    		}
    	}
    }
     
    void _test_write_sprintf(const unsigned long Nb1, const unsigned long Nb2)
    {
    	for(int boucle1 = 0; boucle1 != Nb1; boucle1++)
    	{
    		for(int boucle2 = 0; boucle2 != Nb2; boucle2++)
    		{
    			wchar_t buffer[1024];
    			swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), L"%.5d, %.5d\n", boucle1, boucle2);
    		}
    	}
    }
     
    int main(int argc, char* argv[])
    {
    	int nb0 = 10;
    	int nb1 = 1000;
    	int nb2 = 1000;
     
    	for(int boucle = 0; boucle != nb0; boucle++)
    	{
    		printf("\n", boucle);
    		printf("Passe %d\n", boucle);
     
    		_start_chrono();
    		_test_write_sprintf(nb1, nb2);
    		_display_chrono("write_sprintf");
     
    		_start_chrono();
    		_test_write_string_stream(nb1, nb2);
    		_display_chrono("write_stringstream");
    	}
     
    	return 0;
    }
    Le programme est exécuté en mode release sur un Windows Xp pro SP3 Pentium IV double coeur à 2,8Ghz avec 512 Mo de RAM
    Les résultats sont les suivants:
    write_sprintf : 1.50, 1.50, 1.48, 1.50, 1.50, 1.50, 1.50, 1.50, 1.50, 1.50
    write_stringstream : 7.36, 7.27, 7.33, 7.28, 7.26, 7.27, 7.27, 7.26, 7.27, 7.27
    Il semble donc que l'usage du sprintf (solution du C) soit sur ma machine au moins 5 fois plus rapide que le stringstream (solution du C++)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    C'est un résultat connu.
    En 2001 Herb Sutter obtenait une différence de x8 à x14 suivant les compilateurs.

    La conclusion de son article linké plus haut reste toujours valable de nos jours il me semble. Utiliser par défaut les flux C++, sauf si le profiler révèle un goulet d'étranglement ou si le formatage est extrêmement complexe. Dans ce cas, pas de remord à utiliser snprintf.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Ben disons que je commence à découvrir le C++ et que pour l'instant, je n'avais pas fait le pas pour aller vers les stringstream. Je trouvais sprintf tellement plus "naturel" pour moi (j'ai débuté il y a très longtemps à une époque où l'on commencait à parler de compilateurs qui allait peut être implémenter le C++)

    Ce que je viens de mesurer et lire (merci pour le lien) ne va pas m'encourager à persévérer sur cette voie.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Membre émérite

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    C'est quoi cette manie à toujours regarder les performances ? De nos jours les processeurs effectuent plusieurs milliards d'instructions par secondes, ce qui fait que dans 99% du code, les performances ne sont pas un problème.

    Les problèmes de nos jours sont la sécurité, la robustesse, la maintenance, ... Et dans ces domaines la solution avec stringstream surpasse aisément la solution avec sprintf.

  7. #7
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par Sylvain Togni Voir le message
    C'est quoi cette manie à toujours regarder les performances ?
    Ben dans mon cas, c'est un problème puisque je passe dans cette fonction de formattage un petit millier de fois par seconde et que au bout du compte, cela se voit entre une machine qui pédale à 100%CPU et une à qui il reste de la réserve.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  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
    Par défaut
    Comme cela est souvent dit dans le forum, les problèmes de performances sont souvent à considérés au niveau de l'algo.

  9. #9
    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 : 51
    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
    Par défaut
    Citation Envoyé par Arzar Voir le message
    La conclusion de son article linké plus haut reste toujours valable de nos jours il me semble.
    A la dernière réunion ISO C++ à laquelle j'ai participé, certains (j'ai oublié qui, désolé) débattaient chaudement de ce sujet, et prétendaient que les mauvaises performances des flux n'étaient pas inéluctables, et résultaient en grande partie de mauvaises implémentations.

    Quelques questions :
    - Que se passe-t-il si tu sorts la création du flux de la boucle ?
    - Que se passe-t-il si tu te débrouilles pour que le buffer à l'intérieur du flux soit assez grand dès le début ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je viens de refaire les mesures en prenant en compte les conseils précédents
    • un test avec sprintf
    • un test avec un wstringstream construit et détruit à chaque itération de la boucle
    • un test avec un wstringstream construit une seule fois et vidé à chaque itération de la boucle
    • 10 mesures de 1000 * 1000 itérations pour chaque fonction (résultats en secondes)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void _test_write_sprintf(const unsigned long Nb1, const unsigned long Nb2)
    {
    	for(unsigned int boucle1 = 0; boucle1 != Nb1; boucle1++)
    	{
    		for(unsigned int boucle2 = 0; boucle2 != Nb2; boucle2++)
    		{
    			wchar_t buffer[1024];
    			swprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), L"%.5d, %.5d\n", boucle1, boucle2);
    		}
    	}
    }
    write_sprintf : Elapsed time is 1.61, 1.61, 1.61, 1.61, 1.63, 1.61, 1.61, 1.61, 1.61, 1.61
    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
    void _test_write_string_stream(const unsigned long Nb1, const unsigned long Nb2)
    {
    	for(unsigned int boucle1 = 0; boucle1 != Nb1; boucle1++)
    	{
    		for(unsigned int boucle2 = 0; boucle2 != Nb2; boucle2++)
    		{
    			std::wstringstream str;
    			str	<< std::setw(5) << std::setfill(L'0') << boucle1
    				<< L", "
    				<< std::setw(5) << std::setfill(L'0') << boucle2
    				<< L"\n"
    				;
    		}
    	}
    }
    write_stringstream : Elapsed time is 9.83, 9.81, 9.92, 9.89, 9.81, 9.80, 9.81, 9.81, 9.86, 9.84
    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
    void _test_write_string_stream(const unsigned long Nb1, const unsigned long Nb2)
    {
    	std::wstringstream str;
    	for(unsigned int boucle1 = 0; boucle1 != Nb1; boucle1++)
    	{
    		for(unsigned int boucle2 = 0; boucle2 != Nb2; boucle2++)
    		{
    			str.str(L"");
    			str	<< std::setw(5) << std::setfill(L'0') << boucle1
    				<< L", "
    				<< std::setw(5) << std::setfill(L'0') << boucle2
    				<< L"\n"
    				;
    		}
    	}
    }
    write_stringstream : Elapsed time is 6.02, 6.00, 6.02, 6.02, 6.00, 6.01, 6.05, 6.00, 6.02, 6.03
    Il est donc rentable de sortir de wstringstream de la boucle, de le mettre un peu plus global et de le vider à chaque fois. Le temps de construction/destruction n'est pas négligeable pour cet objet (+63%)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  11. #11
    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
    Par défaut
    J'ai repris ton code dans Visual Express et dans gcc. Avec VE, j'ai des résultats comme les tiens (~ 1 rapport de 1 à 4 entre les 2 fonctions). Avec gcc, la différence n'est plus que de 25% (0.4s contre 0.5s ~). Bon, j'avoue que c'est du brut de fonderie. J'ai pas vérifié l'asm généré par gcc pour voir si il a un peu trop optimisé mon code ou si c'est son implémentation de la stl qui est plus performante.

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

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Quels options sur le compilo? (enfin pour gcc en tout cas).

  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
    Par défaut
    gcc (release) : -Wall -fexceptions -O2
    Visual (release) : /O2 /Ob2 /Oi /Ot /GL /FD /EHsc /MD /Gy /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /U "_HAS_ITERATOR_DEBUGGING" /U "_SECURE_SCL" /errorReport:prompt

  14. #14
    Membre émérite

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Je serais quand même curieux de voire une application ralentie par un stringstream. Les streams servent au formatage textuel, donc à destination des humains, alors que l'opération prenne 1µs ou 10µs, je ne vois pas bien la différence.

  15. #15
    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
    Par défaut
    Citation Envoyé par Sylvain Togni Voir le message
    Les streams servent au formatage textuel, donc à destination des humains
    Pas forcément : ça peut partir sur une socket ou tout autre dispositif de transmission de données. Mais, fondamentalement, tu n'as pas tort : est-ce vraiment le point qui ralentit l'appli (par rapport à une écriture fichier/affichage IHM, envoi sur une interface...).

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

Discussions similaires

  1. Problèmes d'évènements sur ComboBox
    Par bakaneko dans le forum MFC
    Réponses: 3
    Dernier message: 23/02/2004, 08h46
  2. Problème de reqûete sur la date, année et mois en cours
    Par Jean-Marc dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 16/02/2004, 16h36
  3. [CR] Problème de sélection sur un champ date
    Par noluc dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 21/11/2003, 16h56
  4. Problème avec RDTSC sur K6-III
    Par le mage tophinus dans le forum x86 32-bits / 64-bits
    Réponses: 17
    Dernier message: 30/09/2003, 09h43
  5. problème de float sur SQL server 2000.
    Par fidji dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 24/07/2003, 14h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo