Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

écriture des nombres (formatage de sortie)

3 views
Skip to first unread message

KooK

unread,
Jul 4, 2006, 10:40:21 AM7/4/06
to
Bonjour,

Je voudrais écrire les nombres avec un espace tous les 3 chiffres afin
de les rendre plus lisibles. J'ai regardé du coté de setf et setw sans
succès. Suis-je passé à côté ? Quel fonction utiliser ?

exemple :
int main(void)
{
int a = 1000000;
//fonction pour faire afficher 1 000 000
cout << a << endl;
return 0;
}

Si vous savez répondre à la même question en C je suis preneur aussi.

KooK

Olivier Miakinen

unread,
Jul 4, 2006, 1:26:02 PM7/4/06
to
Le 04/07/2006 16:40, KooK a écrit :
>
> Je voudrais écrire les nombres avec un espace tous les 3 chiffres afin
> de les rendre plus lisibles. J'ai regardé du coté de setf et setw sans
> succès. Suis-je passé à côté ? Quel fonction utiliser ?

J'ai bien ça en PHP, mais bon, je ne suis pas sûr que ça t'intéresse...

> exemple :
> int main(void)
> {
> int a = 1000000;
> //fonction pour faire afficher 1 000 000
> cout << a << endl;
> return 0;
> }
>
> Si vous savez répondre à la même question en C je suis preneur aussi.

J'ai relu toute la doc de printf() et fonctions assimilées sans rien
trouver. Je suppose que tu dois pouvoir t'en sortir avec une fonction
qui transforme le nombre en chaîne de caractères (par sprintf() par
exemple) avant de découper le résultat en tranches.

--
Olivier Miakinen
Troll du plus sage chez les conviviaux : le nouveau venu, avec
son clan, s'infiltre dans les groupes de nouvelles. (3 c.)

Sylvain

unread,
Jul 4, 2006, 2:16:11 PM7/4/06
to
KooK wrote on 04/07/2006 16:40:
> Bonjour,
>
> Je voudrais écrire les nombres avec un espace tous les 3 chiffres afin
> de les rendre plus lisibles. J'ai regardé du coté de setf et setw sans
> succès. Suis-je passé à côté ? Quel fonction utiliser ?

pourquoi pas:

ostream& format3(ostream& out, long value)
{
if (value < 1000)
out << value;
else {
register int digit = (int) log10(value);
int divider = (long) pow(10.0, digit - (digit % 3));

long temp = (value / divider) % 1000;
char buff[5];
sprintf(buff, "%i", temp);
out << buff;
for (divider /= 1000; divider > 0; divider /= 1000){
temp = (value / divider) % 1000;
sprintf(buff, " %.03i", temp);
out << buff;
}
}
return out;
}

> Si vous savez répondre à la même question en C je suis preneur aussi.

ça doit marcher aussi.

Sylvain.

Arnaud Debaene

unread,
Jul 4, 2006, 2:21:07 PM7/4/06
to

"KooK" <bl...@free.fr> a écrit dans le message de news:
44aa7d2d$0$31511$626a...@news.free.fr...

> Bonjour,
>
> Je voudrais écrire les nombres avec un espace tous les 3 chiffres afin de
> les rendre plus lisibles. J'ai regardé du coté de setf et setw sans
> succès. Suis-je passé à côté ? Quel fonction utiliser ?
>
> exemple :
> int main(void)
> {
> int a = 1000000;
> //fonction pour faire afficher 1 000 000
> cout << a << endl;
> return 0;
> }


Il faut utiliser les locales, plus particulièrement le facet numpunct :

class MyNumPunct : public std::numpunct<char>
{
protected:
virtual std::string do_grouping() const
{
return "\3"; //groupes de 3 chiffres. Oui, le formattage de cetet
chaine est stupide.....
}

virtual char do_thousands_sep() const
{
return ' '; //séparés par espace
}
};

int main()
{
MyNumPunct* punct=new MyNumPunct(); //will be destroyed by the locale
destructor

//create a new locale based on cout, but using our specific numpunct
std::locale loc(std::cout.getloc (), punct);

std::cout.imbue (loc);
std::cout<<2123456789<<std::endl;
}

cf
http://www.roguewave.com/support/docs/leif/sourcepro/html/stdlibref/num-put.html
pour plus de détails.

Arnaud
MVP - VC


kanze

unread,
Jul 5, 2006, 4:29:43 AM7/5/06
to

> ça doit marcher aussi.

Pourquoi faire simple quand on peut faire compliqué, n'est-ce
pas ? Pour le C++, Arnaud a donné la bonne réponse. En C, c'est
moins évident, mais dans les deux cas, la première chose à
faire, c'est de voir s'il n'y a pas un locale tout fait qui fait
ce que tu veux. Sinon, en C++, on en crée un, comme a expliqué
Arnaud. En C, il faudrait voir au niveau de système comment en
installer un ; C n'offre pas de possibilités d'en créer un à
l'intérieur du programme. (Posix et Linux, par exemple,
fournissent une commande « localedef » pour le faire. En
revanche, en général il faut être root pour pouvoir le faire.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

adeb...@club-internet.fr

unread,
Jul 5, 2006, 11:59:04 AM7/5/06
to

kanze a écrit :

>
> Pourquoi faire simple quand on peut faire compliqué, n'est-ce
> pas ? Pour le C++, Arnaud a donné la bonne réponse.


J'ai un petit doute sur la réponse que j'ai donné magré tout :

int main()
{
MyNumPunct* punct=new MyNumPunct(); //will be destroyed by the
locale
destructor

//create a new locale based on cout, but using our specific numpunct

std::locale loc(std::cout.getloc (), punct);

....

Le fait que la locale appelle delete sur punct dans son destructeur, je
l'observe bien dans mon implémentation (VC2005), mais je n'ai pas
réussi à trouver de documentation "officielle" (ni dans le Josuttis,
ni dans la norme) qui spécifie clairement que c'est un comportement
normal, et comme je trouve que c'est une API un peu bizarre, je me
demande s'il n'y a pas un loup...

Ceci-dit, toute l'API des locale est "bizarre" ;-) Si quelqu'un a une
explication claire sur les règles de gestion des durées de vie des
facets par rapport aux locales, je suis preneur....

Arnaud
MVP - VC

Sylvain

unread,
Jul 5, 2006, 6:27:04 PM7/5/06
to
kanze wrote on 05/07/2006 10:29:
>
> Pourquoi faire simple quand on peut faire compliqué, n'est-ce pas?

tu as raison, j'aurais du écrire:

ostream& format3(ostream& out, long value){

register int digit = (int) log10(value);

long divider = (long) pow(10.0, digit - (digit % 3));
out << ((value / divider) % 1000);


for (divider /= 1000; divider > 0; divider /= 1000){

char buff[5];
sprintf(buff, " %.03i", (value / divider) % 1000);
out << buff;
}
return out;
}

(je laisse le "if (value<0){ out <<'-'; value = -value; }" à la
discrétion du lecteur).

> Pour le C++, Arnaud a donné la bonne réponse. En C, c'est
> moins évident,

en C++ comme en C, qu'est-ce que ostream et string peuvent utiliser
d'autre que sprintf ?? "ils" ont raison, coder un subset sur les mêmes
bases est mal ? intéressant ...

une chose plus intéressante aurait été de préférer une fonction
retournant un std::string afin de l'utiliser dans un chainage de <<
(tout en permettant le formatage à destination d'un string (basic_string
n'héritant pas de ostream) ou, indirectement, d'un ostream).

> mais dans les deux cas, la première chose à
> faire, c'est de voir s'il n'y a pas un locale tout fait

tout fait ou pas, mon locale à moi ((c) 1995 by P.J. Plauger, du
Platform SDK Microsoft 2005) ne contient aucun constructeur avec le
prototype (??, numpunct<?>*); je mets un "??" pour le
"std::cout.getLoc()" car je n'ai pas trouvé de std::cout non plus.

<hs> d'ailleurs je me demande si ce n'est pas un peu pour cela que je
préfère la complexité de mes fonctions de 8 lignes dignes d'une première
matinée d'initiation au C à la simplicité des include ""opaques"" de la
stl. </hs>

Sylvain.

Arnaud Debaene

unread,
Jul 6, 2006, 2:13:01 AM7/6/06
to

"Sylvain" <noS...@mail.net> a écrit dans le message de news:
44ac3c9c$0$872$ba4a...@news.orange.fr...

>
>> mais dans les deux cas, la première chose à
>> faire, c'est de voir s'il n'y a pas un locale tout fait
>
> tout fait ou pas, mon locale à moi ((c) 1995 by P.J. Plauger, du Platform
> SDK Microsoft 2005) ne contient aucun constructeur avec le prototype (??,
> numpunct<?>*); je mets un "??" pour le "std::cout.getLoc()" car je n'ai
> pas trouvé de std::cout non plus.

Ah? J'ai pourtant testé mon exemple avec Visual 2005 sans problèmes ;-)

Arnaud


kanze

unread,
Jul 6, 2006, 5:18:34 AM7/6/06
to
adeb...@club-internet.fr wrote:
> kanze a écrit :

> > Pourquoi faire simple quand on peut faire compliqué,
> > n'est-ce pas ? Pour le C++, Arnaud a donné la bonne réponse.

> J'ai un petit doute sur la réponse que j'ai donné magré tout :

> int main()
> {
> MyNumPunct* punct=new MyNumPunct(); //will be destroyed by the
> locale
> destructor

> //create a new locale based on cout, but using our specific numpunct
>
> std::locale loc(std::cout.getloc (), punct);
> ....

> Le fait que la locale appelle delete sur punct dans son
> destructeur, je l'observe bien dans mon implémentation
> (VC2005), mais je n'ai pas réussi à trouver de documentation
> "officielle" (ni dans le Josuttis, ni dans la norme) qui
> spécifie clairement que c'est un comportement normal, et comme
> je trouve que c'est une API un peu bizarre, je me demande s'il
> n'y a pas un loup...

Dans la norme, §22.1.1.1.2/2 :

The refs arubment to the constructor is used for lifetime
management.

-- For refs == 0, the implementation performs delete
static_cast<locale::facet*>(f) (where f is a pointer to
the facet) when the last locale object containing the
facet is destroyed; for refs == 1, the implementation
never destroys the facet.

Ça, ça fait partie de la déscription de std::locale::facet.
Ensuite, il faut voir que std::numpunct<char> dont tu dérive
dérive de cette classe, qu'elle a aussi un refs paramètre,
qu'elle propage à sa classe de base, que ce paramètre a une
valeur par défaut de 0, et que ton code n'a pas spécifié autre
chose dans la liste d'initialisation.

Le code d'Arnaud était, je crois, à titre d'exemple ; il montre
aussi très bien comme on fait dans une application, au niveau
applicatif. Si on concevait en revanche une classe pour une
bibliothèque, avec beaucoup d'utilisateurs, on ajouterait
probablement aussi un paramètre refs, avec une valeur de défaut
de 0, qu'on propage à la classe de base.

Ce qui permettrait, évidemment, d'utiliser une instance statique
de MyNumPunct.

> Ceci-dit, toute l'API des locale est "bizarre" ;-)

N'est-ce pas:-) ?

> Si quelqu'un a une explication claire sur les règles de
> gestion des durées de vie des facets par rapport aux locales,
> je suis preneur....

Ce que j'ai cité ci-dessus.

Note bien que ce n'est pas sans danger. Si tu veux utiliser une
facette, il faut toujours s'assurer qu'au moins une copie du
locale dont tu l'as obtenu existe. Donc, par exemple, si tu veux
réaliser une comparaison de chaînes insensible à la case des
caractères, tu vas commencer intuitivement par écrire quelque
chose du genre :

class CharEq
{
typedef std::ctype< char >
CType ;
public:
explicit CharEq( std::locale const& l )
: myCType( &std::use_facet< CType >( l ) )
{
}

bool operator()( char lhs, char rhs ) const
{
return myCType->tolower( lhs ) == myCType->tolower( rhs ) ;
}
private:
// pointeur, plutôt que référence, afin de supporter
// l'affectation...
CType const* myCType ;
} ;

Et 99.9% des fois, ça marcherait sans problème. Seulement, tu n'as
aucune garantie -- et un jour ou l'autre, quelqu'un créera un
locale sur la volée, en tant que temporaire, et du coup, tu
risques d'utiliser un objet CType qui a déjà été détruit. La
solution, évident, c'est d'ajouter un membre de type std::locale
à la classe, que tu initialises avec un copie du paramètre du
constructeur, et qui donc assure la pérenité de la facette.

kanze

unread,
Jul 6, 2006, 6:07:13 AM7/6/06
to
Sylvain wrote:
> kanze wrote on 05/07/2006 10:29:

> > Pourquoi faire simple quand on peut faire compliqué, n'est-ce pas?

> tu as raison, j'aurais du écrire:

> ostream& format3(ostream& out, long value){
> register int digit = (int) log10(value);
> long divider = (long) pow(10.0, digit - (digit % 3));
> out << ((value / divider) % 1000);
> for (divider /= 1000; divider > 0; divider /= 1000){
> char buff[5];
> sprintf(buff, " %.03i", (value / divider) % 1000);
> out << buff;
> }
> return out;
> }

Non plus. Pourquoi toutes ces manipulations numériques ?
N'oublie pas non plus qu'il va falloir implémenter la même chose
pour les flottants, et là, les manipulations numériques vont
générer même des erreurs. C'est carrément incompréhensible, et
il fait beaucoup de calculs supplémentaires pour rien.

> (je laisse le "if (value<0){ out <<'-'; value = -value; }" à
> la discrétion du lecteur).

> > Pour le C++, Arnaud a donné la bonne réponse. En C, c'est
> > moins évident,

> en C++ comme en C, qu'est-ce que ostream et string peuvent utiliser
> d'autre que sprintf ??

En C++, ostream ne peut pas très bien utiliser sprintf, parce
que la norme exige qu'il utilise std::num_put (qui doit utiliser
la facette std::numpunct du locale de ios_base qu'il reçoit en
paramètre -- et j'avoue que l'interface est un peu tordue).

En fait, même en C, on préfère snprintf à sprintf, pour des
raisons évidentes. Mais rien ne dit que snprintf n'appelle pas
std::ostringstream.

Mais ce n'est pas réelement l'utilisation de sprintf ici qui me
gène le plus. C'est tout ces calculs inutiles et obfuscants. Si
on rejette ostringstream pour une raison quelconque, et qu'on
préfère sprintf, malgré ces problèmes, je pourrais bien voir une
solution qui commençait à peu près :

char buffer[ sizeof( long ) * CHAR_BIT ] ;
sprintf( buffer, "%d", value ) ;
// ...

Ensuite, on insère les espaces où voulu.

> "ils" ont raison, coder un subset sur les mêmes bases est mal
> ? intéressant ...

Je ne comprends pas cette phrase. Quel sous-ensemble ? De
quoi ? Sur quelles bases ?

> une chose plus intéressante aurait été de préférer une
> fonction retournant un std::string afin de l'utiliser dans un
> chainage de << (tout en permettant le formatage à destination
> d'un string (basic_string n'héritant pas de ostream) ou,
> indirectement, d'un ostream).

C'est effectivement une altérnative intéressante. Quand j'ai
implémenté Gabi::Format (ou GB_Format, comme il s'appelait
alors), je me suis bien arrangé pour qu'il supporte une
conversion en std::string (ou en GB_String, dans les premières
versions, qui ont précédé la norme) aussi bien que l'opérateur
<<. (Pour ceux que ça intéresse, le code de Gabi::Format est
encore disponible à
http://kanze.james.neuf.fr/code/Old/Text/Format/index.html. Mais
ça fait un moment que je ne le maintiens plus -- dans la
pratique, le formattage à la printf est tout sauf intuitif. En
revanche, les dernières mises-à-jour datent d'une époque où je
ne pouvais pas encore compter sur un support des locales C++. Du
coup, j'ai implémenté ma propre internationalisation. Y compris
le gestion des séparateurs des milliers.)

> > mais dans les deux cas, la première chose à faire, c'est de
> > voir s'il n'y a pas un locale tout fait

> tout fait ou pas, mon locale à moi ((c) 1995 by P.J. Plauger,
> du Platform SDK Microsoft 2005) ne contient aucun constructeur
> avec le prototype (??, numpunct<?>*); je mets un "??" pour le
> "std::cout.getLoc()" car je n'ai pas trouvé de std::cout non
> plus.

Tu n'as pas dû bien régarder, parce que le code d'Arnaud marche
bien sur ma copie de VC++ 2005. Le contraire m'aurait d'ailleurs
étonné ; Dinkumware est probablement celui qui supporte le plus
en questions de std::locale. Je ne crois pas qu'il soit livré
avec le compilateur Microsoft, mais je sais qu'ils ont des
locales tout faits qui supporte ce qui a été démandé.

> <hs> d'ailleurs je me demande si ce n'est pas un peu pour cela
> que je préfère la complexité de mes fonctions de 8 lignes
> dignes d'une première matinée d'initiation au C à la
> simplicité des include ""opaques"" de la stl. </hs>

On a déjà compris ici. Tu n'as pas envie d'apprendre de
nouvelles techniques. Quoiqu'elles puissent apporter.

KooK

unread,
Jul 6, 2006, 10:49:14 AM7/6/06
to
Arnaud Debaene a écrit :

> Il faut utiliser les locales, plus particulièrement le facet numpunct :
>
> class MyNumPunct : public std::numpunct<char>
> {
> protected:
> virtual std::string do_grouping() const
> {
> return "\3"; //groupes de 3 chiffres. Oui, le formattage de cetet
> chaine est stupide.....
> }
>
> virtual char do_thousands_sep() const
> {
> return ' '; //séparés par espace
> }
> };
>
> int main()
> {
> MyNumPunct* punct=new MyNumPunct(); //will be destroyed by the locale
> destructor
>
> //create a new locale based on cout, but using our specific numpunct
> std::locale loc(std::cout.getloc (), punct);
>
> std::cout.imbue (loc);
> std::cout<<2123456789<<std::endl;
> }
>
> cf
> http://www.roguewave.com/support/docs/leif/sourcepro/html/stdlibref/num-put.html
> pour plus de détails.
>
> Arnaud
> MVP - VC
>
>

Merci pour cette réponse, je ne connaissais pas le système des locales.
Je suis même surpris de voir que ma question a mené tant de réflexions.

Chez moi ta réponse marche très bien (g++, Debian), mais j'ai pu faire
encore plus simple :
int main(void)
{
double pi_M = 3141.5926;
//pour afficher correctement
cout.setf(ios::fixed);
cout << setprecision(4);
cout << pi_M << endl; //3141.5926
//pour comparer les sorties
printf("printf : %.4f\n", pi_M); //3141.5926

cout << "cout.imbue(cout.getloc())\n";
//meme resultat que locale::global(locale(""));
cout.imbue(cout.getloc());
cout << pi_M << endl; //3141.5926
printf("printf : %.4f\n", pi_M); //3141,5926 -> la virgule

cout << "cout.imbue(locale::locale(\"fr_FR.UTF-8\"))\n";
cout.imbue(locale::locale("fr_FR.UTF-8"));
cout << pi_M << endl; //3 141,5926 -> OK
printf("printf : %.4f\n", pi_M); //3141,5926 -> pas d'espace

return 0;
}

Voilà en choisissant tout simplement la bonne locale :P , pas sûr que
sous windows ça marche (mais je m'en moque). En C le mécanisme est
analogue d'après ce que j'ai lu.
Par contre j'imagine que si je veux grouper les décimales par trois il
va falloir que je dérive _mais je me sers de moins de 3 décimales pour
le moment.

Encore merci,
KooK

Olivier Miakinen

unread,
Jul 6, 2006, 11:04:01 AM7/6/06
to
Le 06/07/2006 16:49, KooK a écrit :

>> [...]


>
> cout << "cout.imbue(locale::locale(\"fr_FR.UTF-8\"))\n";
> cout.imbue(locale::locale("fr_FR.UTF-8"));
> cout << pi_M << endl; //3 141,5926 -> OK
> printf("printf : %.4f\n", pi_M); //3141,5926 -> pas d'espace
>
> return 0;
> }
>
> Voilà en choisissant tout simplement la bonne locale :P , pas sûr que
> sous windows ça marche (mais je m'en moque). En C le mécanisme est
> analogue d'après ce que j'ai lu.

Il serait intéressant de voir ce que cela donne pour l'Inde et le
Pakistan (malheureusement je ne connais pas les codes de langue et
de pays).

<cit. http://www.miakinen.net/vrac/nombres#chiffres>
Dans quelques pays (Inde et Pakistan), les chiffres sont séparés
par paires, sauf les 3 premiers (10,00,000 = 1 000 000) [quid].
</>

> Par contre j'imagine que si je veux grouper les décimales par trois il
> va falloir que je dérive _mais je me sers de moins de 3 décimales pour
> le moment.

Dans mes recherches pour ma page sur l'écriture des nombres, je n'ai
rien trouvé à propos d'une éventuelle séparation des décimales. Par
défaut, je supposerais donc qu'il n'y en a pas (et que le comportement
que tu as constaté est donc correct).

--
Olivier Miakinen

Olivier Miakinen

unread,
Jul 6, 2006, 11:31:01 AM7/6/06
to
Le 06/07/2006 17:04, Olivier Miakinen a écrit :
>
> Il serait intéressant de voir ce que cela donne pour l'Inde et le
> Pakistan (malheureusement je ne connais pas les codes de langue et
> de pays).

J'ai trouvé : dans les deux cas c'est en hindi, code "hi" (j'ignore si
le nom du pays est obligatoire).

> <cit. http://www.miakinen.net/vrac/nombres#chiffres>
> Dans quelques pays (Inde et Pakistan), les chiffres sont séparés
> par paires, sauf les 3 premiers (10,00,000 = 1 000 000) [quid].
> </>

Confirmation sur <http://joel.toonywood.org/blog/2005-08.html#e.19> :

<cit.>
Petite curiosité au sujet des chiffres, en Inde, ils ne séparent pas par
milliers comme on le fait (milliers, millions, milliards, ...), mais
regroupent d'abord les trois derniers chiffres comme nous, ensuite,
c'est cent mille (1,00,000) aussi appelé lakh, et après dix millions
(1,00,00,000) : crore [...]
</cit.>

>> Par contre j'imagine que si je veux grouper les décimales par trois il
>> va falloir que je dérive _mais je me sers de moins de 3 décimales pour
>> le moment.
>
> Dans mes recherches pour ma page sur l'écriture des nombres, je n'ai
> rien trouvé à propos d'une éventuelle séparation des décimales. Par
> défaut, je supposerais donc qu'il n'y en a pas (et que le comportement
> que tu as constaté est donc correct).

Là, la question reste ouverte.

kanze

unread,
Jul 6, 2006, 1:09:52 PM7/6/06
to
Olivier Miakinen wrote:
> Le 06/07/2006 16:49, KooK a écrit :

> >> [...]

> > cout << "cout.imbue(locale::locale(\"fr_FR.UTF-8\"))\n";
> > cout.imbue(locale::locale("fr_FR.UTF-8"));
> > cout << pi_M << endl; //3 141,5926 -> OK
> > printf("printf : %.4f\n", pi_M); //3141,5926 -> pas d'espace

> > return 0;
> > }

> > Voilà en choisissant tout simplement la bonne locale :P ,
> > pas sûr que sous windows ça marche (mais je m'en moque). En
> > C le mécanisme est analogue d'après ce que j'ai lu.

> Il serait intéressant de voir ce que cela donne pour l'Inde et
> le Pakistan (malheureusement je ne connais pas les codes de
> langue et de pays).

> <cit. http://www.miakinen.net/vrac/nombres#chiffres>
> Dans quelques pays (Inde et Pakistan), les chiffres sont séparés
> par paires, sauf les 3 premiers (10,00,000 = 1 000 000) [quid].
> </>

C'est prévu. Il faut simplement que do_grouping renvoie "\3\2"
(et que do_thousands_sep renvoie ',', évidemment). La règle,
c'est que le dernier grouping se répète.

Plus intéressant, c'est le cas de l'arabe, où les chiffres
apparaissent avec le chiffre de poids faible d'abord, à
l'inverse des notres, du point de vue de la direction normale de
l'écriture.

> > Par contre j'imagine que si je veux grouper les décimales
> > par trois il va falloir que je dérive _mais je me sers de
> > moins de 3 décimales pour le moment.

> Dans mes recherches pour ma page sur l'écriture des nombres,
> je n'ai rien trouvé à propos d'une éventuelle séparation des
> décimales. Par défaut, je supposerais donc qu'il n'y en a pas
> (et que le comportement que tu as constaté est donc correct).

Je suppose par là qu'il veut dire : les chiffres derrière le
décimal. En effet, la norme ne prévoit rien. Dans la pratique,
je crois que c'est assez arbitraire ; ça ne m'étonnerait pas,
par exemple, de voir une table de logrithmes où les chiffres
sont régroupés par cinq. D'après mes souvenirs, Plauger a dit
une fois que son implémentation (donc, celle de VC++) a une
extension pour le supporter, mais je n'en sais pas plus (et
l'extension n'est peut-être présente que dans les versions
étendues de la bibliothèque qu'il vend directement).

Olivier Miakinen

unread,
Jul 6, 2006, 1:33:24 PM7/6/06
to
Le 06/07/2006 19:09, kanze a écrit :
>
>> Il serait intéressant de voir ce que cela donne pour l'Inde et
>> le Pakistan (malheureusement je ne connais pas les codes de
>> langue et de pays).
>
>> <cit. http://www.miakinen.net/vrac/nombres#chiffres>
>> Dans quelques pays (Inde et Pakistan), les chiffres sont séparés
>> par paires, sauf les 3 premiers (10,00,000 = 1 000 000) [quid].
>> </>
>
> C'est prévu. Il faut simplement que do_grouping renvoie "\3\2"
> (et que do_thousands_sep renvoie ',', évidemment). La règle,
> c'est que le dernier grouping se répète.

C'est une bonne nouvelle.

> Plus intéressant, c'est le cas de l'arabe, où les chiffres
> apparaissent avec le chiffre de poids faible d'abord, à
> l'inverse des notres, du point de vue de la direction normale de
> l'écriture.

Je ne savais pas comment c'était traité en C et C++, mais dans les
pages HTML avec Unicode, c'est juste un peu plus compliqué que ça :
les chiffres apparaissent bien dans le même « ordre » que pour nous
(chiffre de poids fort en premier), mais c'est la direction d'écriture
qui change en cours de route (de right-to-left pour les lettres, elle
passe temporairement à left-to-right pour les nombres).

Si la même convention existait en français, le texte « Voilà 542 euros »
s'écrirait ainsi :

V
oV
ioV
lioV
àlioV
àlioV
5 àlioV
54 àlioV
542 àlioV
542 àlioV
e 542 àlioV
ue 542 àlioV
rue 542 àlioV
orue 542 àlioV
sorue 542 àlioV

>> Dans mes recherches pour ma page sur l'écriture des nombres,
>> je n'ai rien trouvé à propos d'une éventuelle séparation des
>> décimales. Par défaut, je supposerais donc qu'il n'y en a pas
>> (et que le comportement que tu as constaté est donc correct).
>
> Je suppose par là qu'il veut dire : les chiffres derrière le
> décimal.

Oui, exactement. En français on dirait « les chiffres après la
virgule », ou « les chiffres après le point décimal » si on parle
d'un texte anglais. Mais on les appelle aussi tout simplement les
« décimales ».

<cit. http://atilf.atilf.fr/>
DÉCIMALE
II. Substantif
A. Subst. fém.
1. MATH. Chiffre placé à droite de la virgule dans un nombre décimal.
</cit.>

> En effet, la norme ne prévoit rien. Dans la pratique,
> je crois que c'est assez arbitraire ; ça ne m'étonnerait pas,
> par exemple, de voir une table de logrithmes où les chiffres
> sont régroupés par cinq.

Oui, je reconnais que tu as raison : j'en ai déjà vu.

> D'après mes souvenirs, Plauger a dit
> une fois que son implémentation (donc, celle de VC++) a une
> extension pour le supporter, mais je n'en sais pas plus (et
> l'extension n'est peut-être présente que dans les versions
> étendues de la bibliothèque qu'il vend directement).

Ok.

--
Olivier Miakinen

Sylvain

unread,
Jul 6, 2006, 5:23:36 PM7/6/06
to
Arnaud Debaene wrote on 06/07/2006 08:13:
>
> Ah? J'ai pourtant testé mon exemple avec Visual 2005 sans problèmes ;-)

j'ai indiqué "Platform SDK" (package bin/inc/lib) pas clean-install de
vs2005, ça fait surement une diff sur le contenu.

et tu l'as testé avec les include idoines, comme mon vocabulaire de base
se limite à stdio.h et string.h, ça ne pouvoit pas compiler tout seul -
c'est peut être une idée utile d'indiquer ses incl, non ?

Sylvain.

Sylvain

unread,
Jul 6, 2006, 5:39:52 PM7/6/06
to
kanze wrote on 06/07/2006 12:07:
>
> Non plus. Pourquoi toutes ces manipulations numériques ?

si je t'indique que c'est pour satisfaire à l'énoncé, je pense que tu ne
comprendras pas plus.

> il fait beaucoup de calculs supplémentaires pour rien.

cites-en seulement un !

> [............] Mais rien ne dit que snprintf n'appelle pas
> std::ostringstream.

"rien" ... enfin sauf le code source du runtime (ou bcp plus accessible
des std lib), non ?

> char buffer[ sizeof( long ) * CHAR_BIT ] ;

surréservation inutile (soit, la pile survivra) et basée sur rien,
pourquoi CHAR_BIT/2 octets par digit? il en faut 1 ou 2; qu'advient-il
si la séparateur est ".-.-.-.-." et non plus " " ?

> sprintf( buffer, "%d", value ) ;

> Ensuite, on insère les espaces où voulu.

en couteuse recopie ? pas terrible comme solution.

> On a déjà compris ici. Tu n'as pas envie d'apprendre de
> nouvelles techniques. Quoiqu'elles puissent apporter.

pouf, pouf, ben alors non, "on" n'a encore pas tout compris.

Sylvain.

Falk Tannhäuser

unread,
Jul 6, 2006, 7:00:25 PM7/6/06
to
Sylvain wrote:
>> sprintf( buffer, "%d", value ) ;
>> Ensuite, on insère les espaces où voulu.
>
> en couteuse recopie ? pas terrible comme solution.

Coûteuse en temps d'exécution, par rapport aux log10(), pow(),
sprintf() multiples et diverses multiplications et divisions
(non remplaçables par des simples décalages...) ?
Autre question : Qu'est-ce qui nous garantit que log10(1000)
ne donne pas par exemple 2.99999999999999956 sur certains systèmes
- valeur qui sera arrondie à 2 lors de la conversion en int ?

Falk

Sylvain

unread,
Jul 6, 2006, 9:22:18 PM7/6/06
to
Falk Tannhäuser wrote on 07/07/2006 01:00:
>
> Coûteuse en temps d'exécution, par rapport aux log10(), pow(),
> sprintf() multiples

log10 et pow sont couteuses, donc je les ai utilisé une fois (pas de
"multiples" fois).

sprintf est, dans le source de mon CRT, la primitive utilisée par tous
les injecteurs de ostream (sauf <<(char*) qui copie direct.t) si c'est
couteux c'est hélas pour tout le monde.

> diverses multiplications et divisions
> (non remplaçables par des simples décalages...) ?

oulaaaa, mais c'est strictement interdit ici - tu vois James,
"j'apprends" ;)

> Autre question : Qu'est-ce qui nous garantit que log10(1000)
> ne donne pas par exemple 2.99999999999999956 sur certains systèmes
> - valeur qui sera arrondie à 2 lors de la conversion en int ?

en effet, on préférera un log10(value + 1)
(l'erreur plus systématique est ici log(0)).

Sylvain.

Arnaud Debaene

unread,
Jul 7, 2006, 2:19:13 AM7/7/06
to

"Sylvain" <noS...@mail.net> a écrit dans le message de news:
44ad7f56$0$832$ba4a...@news.orange.fr...

#include <iostream>
#include <locale>

Ceci-dit, tu n'as pas indiqué les tiens non plus ;-)

Et puis, quand tu dis que tu ne connas pas std::cout, comment dire.... Ta
crédibilité en prend un peu un coup en ce qui concerne le C++...

Arnaud


kanze

unread,
Jul 7, 2006, 4:14:00 AM7/7/06
to
Arnaud Debaene wrote:
> "Sylvain" <noS...@mail.net> a écrit dans le message de news:
> 44ad7f56$0$832$ba4a...@news.orange.fr...
> > Arnaud Debaene wrote on 06/07/2006 08:13:

> > et tu l'as testé avec les include idoines, comme mon
> > vocabulaire de base se limite à stdio.h et string.h, ça ne
> > pouvoit pas compiler tout seul - c'est peut être une idée
> > utile d'indiquer ses incl, non ?

> #include <iostream>
> #include <locale>

Pour être conforme, il faudrait aussi inclure <ostream>. Et
peut-être <string>, bien que je ne vois pas comment <locale>
puisse ne pas l'inclure.

> Ceci-dit, tu n'as pas indiqué les tiens non plus ;-)

En général, on suppose que le lecteur sache assez du C++ pour
savoir qu'il faut inclure les en-têtes pour avoir accès aux noms
qui y sont déclarés. Si on n'indique pas d'#include, il va de
soi qu'il faut en ajouter. (Si on indique un ou plusieurs
#include, c'est mieux d'être complet, et les indique tous. Bien
que ça ne me pose pas de problème si on indique des includes
non-standard, genre Boost, mais pas ceux de la norme.)

> Et puis, quand tu dis que tu ne connas pas std::cout, comment
> dire.... Ta crédibilité en prend un peu un coup en ce qui
> concerne le C++...

Même sans connaître le C++... En C, si on fait :
setlocale( LC_ALL, "fr_FR.UTF-8" );
(en supposant que "fr_FR.UTF-8" soit un locale qui fait ce qu'on
veut), printf doit aussi insérer les blancs.

kanze

unread,
Jul 7, 2006, 4:37:12 AM7/7/06
to
Sylvain wrote:
> kanze wrote on 06/07/2006 12:07:

> > Non plus. Pourquoi toutes ces manipulations numériques ?

> si je t'indique que c'est pour satisfaire à l'énoncé, je pense
> que tu ne comprendras pas plus.

Je ne vois effectivement aucun rapport avec l'énoncé du
problème. Le problème, c'est de convertir une valeur en texte,
avec un certain format. Quelqu'un qui écrit des trucs tordus
comme ce que tu as posté se trouverait vite muté à une poste où
il n'écrit pas de code dans les boîtes où j'ai travaillé.

> > il fait beaucoup de calculs supplémentaires pour rien.

> cites-en seulement un !

Un pow() et un log10(), pour commencer. Et toutes ces
manipulations en virgule flottant, quand le problème ne concerne
que les entiers -- le virgule flottant est à éviter tant que ce
n'est pas nécessaire.

> > [............] Mais rien ne dit que snprintf n'appelle pas
> > std::ostringstream.

> "rien" ... enfin sauf le code source du runtime (ou bcp plus
> accessible des std lib), non ?

Si tu veux t'amuser à lire le code source de la bibliothèque
standard... Et ça ne t'apprend que sur une implémentation bien
précises.

> > char buffer[ sizeof( long ) * CHAR_BIT ] ;

> surréservation inutile (soit, la pile survivra) et basée sur
> rien, pourquoi CHAR_BIT/2 octets par digit?

C'est simplement l'expression la plus simple qui garantit assez
de mémoire quelque soit la base. (En fait, en général, j'ajoute
un pour le '\0'. Comme ça, ça marche pour une conversion en base
2 aussi.) Je sais qu'en cas de base 10, je peux trouver des
expressions qui surallouent un peu moins, mais pourquoi me
casser la tête. Qui peut le plus peu le moins.

> il en faut 1 ou 2; qu'advient-il
> si la séparateur est ".-.-.-.-." et non plus " " ?

Je converis un entier, sans séparateur. Je sépare les
concernes : la convertion et l'insertion sont deux concernes
indépendant.

> > sprintf( buffer, "%d", value ) ;
> > Ensuite, on insère les espaces où voulu.

> en couteuse recopie ? pas terrible comme solution.

Une coûteuse récopie ? Récopie, oui, mais c'est une parmi
combien ? Et coûteuse ? Ou bien, tu te moques du monde, ou
bien, tu ne sais vraiment pas de quoi tu parles. (Et ça de
quelqu'un qui s'amuse à passer par des flottants, avec des coup
de pow() et de log10().)

Est-ce que tu as réelement fait du profiling des solutions
différentes, pour savoir ce qui coûtait et ce qui ne coûtait
pas ? Ou est-ce que (ce dont je suis assez sûr) le programme
était assez rapide déjà que ça ne valait pas la peine.

kanze

unread,
Jul 7, 2006, 4:53:04 AM7/7/06
to
Olivier Miakinen wrote:
> Le 06/07/2006 19:09, kanze a écrit :

[...]


> > Plus intéressant, c'est le cas de l'arabe, où les chiffres
> > apparaissent avec le chiffre de poids faible d'abord, à
> > l'inverse des notres, du point de vue de la direction normale de
> > l'écriture.

> Je ne savais pas comment c'était traité en C et C++, mais dans les
> pages HTML avec Unicode, c'est juste un peu plus compliqué que ça :
> les chiffres apparaissent bien dans le même « ordre » que pour nous
> (chiffre de poids fort en premier), mais c'est la direction d'écriture
> qui change en cours de route (de right-to-left pour les lettres, elle
> passe temporairement à left-to-right pour les nombres).

C'est une solution. Je vois en effet qu'ils ont une catégorie
spéciale pour la bidirectionalité des chiffres
« ARABIC-INDIC » (les chiffres qui servent habituellement dans
l'arabe). J'avoue qu'a priori, ce n'est pas ce auquel je me
serais attendu ; ça veut dire que même si j'ai un texte
entièrement en arabe, il faut que je m'occupe de la
bi-directionnalité. Mais dans la pratique, je doute que ce soit
un problème. Je ne crois pas qu'il y a des logiciels qui
puissent traiter l'arabe et qui ne permettent pas des mots en
alphabet latin, et donc, tous les logiciels qui traitent de
l'arabe vont avoir à gérer la bidirectionalité quand même. (Si
on s'y intéresse, voir http://www.unicode.org/reports/tr9/.)

[...]


> >> Dans mes recherches pour ma page sur l'écriture des nombres,
> >> je n'ai rien trouvé à propos d'une éventuelle séparation des
> >> décimales. Par défaut, je supposerais donc qu'il n'y en a pas
> >> (et que le comportement que tu as constaté est donc correct).

> > Je suppose par là qu'il veut dire : les chiffres derrière le
> > décimal.

> Oui, exactement. En français on dirait « les chiffres après la
> virgule », ou « les chiffres après le point décimal » si on
> parle d'un texte anglais. Mais on les appelle aussi tout
> simplement les « décimales ».

> <cit. http://atilf.atilf.fr/>
> DÉCIMALE
> II. Substantif
> A. Subst. fém.
> 1. MATH. Chiffre placé à droite de la virgule dans un nombre décimal.
> </cit.>

Merci pour l'information. C'est une subtilité du français que je
ne connaissais pas.

Sylvain

unread,
Jul 7, 2006, 6:13:15 PM7/7/06
to
Arnaud Debaene wrote on 07/07/2006 08:19:
>
> Ceci-dit, tu n'as pas indiqué les tiens non plus ;-)

ben si, stdio.h et string.h, indication retardée, ok ;)

> Et puis, quand tu dis que tu ne connas pas std::cout, comment dire....
> Ta crédibilité en prend un peu un coup en ce qui concerne le C++...

si c'est ma crédibilité ça va, j'ai eu peur pour ma compétence.

c'était un demi-joke; tous les outils MS avant VS2005 définissaient
'cout' dans le global namespace et non sous 'std::'; ils (avec cin et
ses copains) est enfin dans un bloc _STD_BEGIN / _STD_END avec un

#if defined(__cplusplus)
#define _STD_BEGIN namespace std {
#define _STD_END }
#else /* __cplusplus */
#define _STD_BEGIN
#define _STD_END
#endif

Sylvain.

Sylvain

unread,
Jul 7, 2006, 6:27:09 PM7/7/06
to
kanze wrote on 07/07/2006 10:14:
>
> En général, on suppose que le lecteur sache assez du C++ pour
> savoir qu'il faut inclure les en-têtes pour avoir accès aux noms
> qui y sont déclarés. Si on n'indique pas d'#include, il va de
> soi qu'il faut en ajouter.

certes, mais tu connais les jeunes, tjrs prompt à sauter des étapes,
pour le bien pédagogique de l'exposé d'une solution, cet ajout (non
systématique) peut être utile.

> Même sans connaître le C++... En C, si on fait :
> setlocale( LC_ALL, "fr_FR.UTF-8" );
> (en supposant que "fr_FR.UTF-8" soit un locale qui fait ce qu'on
> veut), printf doit aussi insérer les blancs.

il devrait !! en effet, est-ce le cas avec gcc ? ce sagouin de visual
lui ne daigne prendre en compte les locales que pour strftime (peut être
1 ou 2 autres).

Sylvain.

Sylvain

unread,
Jul 7, 2006, 6:40:35 PM7/7/06
to
kanze wrote on 07/07/2006 10:37:
>
> [..] Quelqu'un qui écrit des trucs tordus

> comme ce que tu as posté se trouverait vite muté à une poste où
> il n'écrit pas de code dans les boîtes où j'ai travaillé.

j'espère bien !

> Un pow() et un log10(), pour commencer.

et des %, très mauvais les % !!

> Si tu veux t'amuser à lire le code source de la bibliothèque
> standard... Et ça ne t'apprend que sur une implémentation bien
> précises.

je croyais tenir de toi qu'il n'y avait pas tant d'implémentations de la
STL que ça sur le marché, et qu'au contraire la distrib. de Plauger
était fréquemment choisie ?! oui, non, peut-être ?

> C'est simplement l'expression la plus simple qui garantit assez
> de mémoire quelque soit la base.

c'est vrai, là j'ai frissé la mauvaise foi, introduire la taille
registre d'un long est même une bonne idée.

> Une coûteuse récopie ? Récopie, oui, mais c'est une parmi
> combien ? Et coûteuse ? Ou bien, tu te moques du monde, ou
> bien, tu ne sais vraiment pas de quoi tu parles.

c'est ce que je me suis demandé lorsque l'on m'a soumit ce code, passé
le stupeur j'ai séché sur le conseil à donner (mis à part
"flingues-toi"), vous m'avez un peu rassuré sur le peu de compassion
possible dans de tels cas - ma solution n'est peut être pas idéale mais
inspirée du bon sens que tu as cité (conversion et formatage sont 2 op.
distinctes)

pour l'anecdote:

String& operator << (String& inString, long int32){
static char temp[48];
char* p = temp;
ltoa(int32, p, inString.getRadix());
register char sep = inString.getSep();
if (sep){
char cnt = (inString.getRadix() == 10) ? 3 : 2;
char* frst = temp + (*temp == '-');
char* curr = strchr(temp, '\0');
p += sizeof(temp);
*--p = 0;
for (char in = 0; curr != frst; ++in){
if (in == cnt)
*--p = sep, in = 0;
*--p = *--curr;
}
if (*temp == '-')
*--p = '-';
}
return inString.append(p, ::strlen(p));
}

itoa / ltoa ne sont pas standards mais il existe de nbrx portages.

Sylvain.

Olivier Miakinen

unread,
Jul 8, 2006, 9:29:03 AM7/8/06
to
Le 07/07/2006 10:53, kanze a écrit :
>
> (Si on s'y intéresse, voir http://www.unicode.org/reports/tr9/.)

Merci pour le lien. J'ai eu un peu de mal à tout lire, mais le sujet est
passionnant.

> [...] une subtilité du français que je ne connaissais pas.

Il m'a semblé que tu n'étais peut-être pas francophone de naissance,
quoique tu t'exprimes vraiment bien dans cette langue... et des
subtilités comme celle-là il y en a des quantités !

Bon, eh bien je crois que je me suis beaucoup éloigné du thème du groupe
qui est, si je ne m'abuse, le C++. Aussi je propose un suivi en privé si
jamais il y avait encore quelque chose à dire (mais je pense que non).

Cordialement,
--
Olivier Miakinen

James Kanze

unread,
Jul 9, 2006, 7:28:11 AM7/9/06
to
Sylvain wrote:
> kanze wrote on 07/07/2006 10:14:

>> En général, on suppose que le lecteur sache assez du C++ pour
>> savoir qu'il faut inclure les en-têtes pour avoir accès aux noms
>> qui y sont déclarés. Si on n'indique pas d'#include, il va de
>> soi qu'il faut en ajouter.

> certes, mais tu connais les jeunes, tjrs prompt à sauter des étapes,
> pour le bien pédagogique de l'exposé d'une solution, cet ajout (non
> systématique) peut être utile.

>> Même sans connaître le C++... En C, si on fait :
>> setlocale( LC_ALL, "fr_FR.UTF-8" );
>> (en supposant que "fr_FR.UTF-8" soit un locale qui fait ce qu'on
>> veut), printf doit aussi insérer les blancs.

> il devrait !! en effet, est-ce le cas avec gcc ?

Ça dépend de l'installation. La plupart du temps, sous Unix, gcc
utilise les bibliothèques du système pour ce qui est de la
bibliothèque C. Ce qui fait que ça peut varier d'une
installation à l'autre.

Aussi, il n'y a de norme en ce qui concerne le comportement des
locales que pour les locales "C" et "POSIX", et la norme C
n'exige la présence que le locale "C". Posix (je crois) spécifie
aussi le nommage des locales, mais c'est toujours aux
fournisseurs de décider ce que c'est réelement un locale du
genre "fr_FR.UTF-8". Jusqu'à certaines limites. L'encodage doit
bien être UTF-8, ce qui joue aussi sur des fonctions du genre
isalpha, etc. Mais autant que je sache, il n'y a aucune norme
qui spécifie comment le locale fr_FR formatte des entiers. Et
sur mon Linux, il n'insère pas d'espace. D'où l'intérêt
d'utiliser C++, et de créer le locale comme l'a précisé
Arnaud ; c'est garanti sur n'importe quel implémentation de
C++.

Et en passant, je ne trouve pas le texte dans la norme C qui dit
que les conversions dans fprintf dépendent du locale. On voit
mal l'intérêt des locales sinon, et Unix (mais non Posix)
l'exige, mais seulement si on a un caractère de flag (un des
caractères spéciaux qui précèdent la largueur) de `. Et j'ai
l'impression que Linux n'est pas Unix à cet égard. (Il me semble
déjà avoir constaté qu'il ne supporte pas les spécifications de
formattage positionnel non plus.)

> ce sagouin de visual lui ne daigne prendre en compte les
> locales que pour strftime (peut être 1 ou 2 autres).

Pour printf et compagnie, il semble qu'en fait, j'ai confondu
une extension Unix à la norme C. (À l'époque où j'ai implémenté
la bibliothèque standard de C, il n'y avait pas encore de norme
C, et j'implémentais la norme X/Open de l'époque.)

Encore une raison à préférer les iostream, il me semble.

--
James Kanze kanze...@neuf.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

James Kanze

unread,
Jul 9, 2006, 7:32:57 AM7/9/06
to
Sylvain wrote:

> c'était un demi-joke; tous les outils MS avant VS2005 définissaient
> 'cout' dans le global namespace et non sous 'std::';

Ce n'était pas le cas de VC++ 6.0, où cout se trouvait bien dans
std::. En fait, VC++ 6.0 fournissait deux versions complètes et
distinctes des iostream : les iostream classique, dans
<iostream.h>, et dans le namespace global, et les iostream
standard, dans <iostream>, <ostream>, et al., et dans std::. On
utilisait la première si on avait des problèmes de compatibilité
avec du code existant, et la seconde autrement.

J'imagine que ç'aurait été amusant si on commençait un
programme :

#include <iostream.h>
#include <iostream>

using namespace std ;

Il devait y avoir pas mal de conflits.

--
James Kanze kanze...@neuf.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Sylvain

unread,
Jul 9, 2006, 7:52:38 AM7/9/06
to
James Kanze wrote on 09/07/2006 13:32:
>
> Ce n'était pas le cas de VC++ 6.0, où cout se trouvait bien dans
> std::. En fait, VC++ 6.0 fournissait deux versions complètes et
> distinctes des iostream : les iostream classique, dans
> <iostream.h>, et dans le namespace global, et les iostream
> standard, dans <iostream>, <ostream>, et al., et dans std::.

oups, tu as raison, j'ai été abusé par le pattern "all C/C++ files" du
'search [in files]' qui n'inclut pas '*.' (dommage!).

Sylvain.

James Kanze

unread,
Jul 9, 2006, 8:09:21 AM7/9/06
to
Sylvain wrote:
> kanze wrote on 07/07/2006 10:37:

>> [..] Quelqu'un qui écrit des trucs tordus
>> comme ce que tu as posté se trouverait vite muté à une poste où
>> il n'écrit pas de code dans les boîtes où j'ai travaillé.

> j'espère bien !

>> Un pow() et un log10(), pour commencer.

> et des %, très mauvais les % !!

Pourquoi ? Si les paramètres sont positifs, ils donnent un
résultat précis.

>> Si tu veux t'amuser à lire le code source de la bibliothèque
>> standard... Et ça ne t'apprend que sur une implémentation
>> bien précises.

> je croyais tenir de toi qu'il n'y avait pas tant
> d'implémentations de la STL que ça sur le marché,

Dans la pratique, toutes les implémentations de la STL dérivent
d'une source commune. Il y a assez de temps, néaumoins, qu'il y
a des divergences importantes, et on ne peut pas dire que
l'implémentation Dinkumware soit identique à celle de Roguewave.

Mais ici, il ne s'agit pas de la STL, mais des iostream. Où la
situation est bien différente, et où il y avait déjà pas mal
d'implémentations complètement indépendantes. (En tout cas,
celle de Roguewave, celle de g++ et celle de Dinkumware sont
tous les trois bien différents.)

> et qu'au contraire la distrib. de Plauger était fréquemment
> choisie ?! oui, non, peut-être ?

D'après mes expériences, l'implémentation Dinkumware (qui est
sous le contrôle de Plauger, même s'il n'y est pas seul) est la
meilleur. Dans le temps, j'aurais dit de loin le meilleur, mais
celle de g++ arrive maintenant à à peu près le même niveau. Au
moins deux compilateurs, VC++ et Visual Age, utilisent
Dinkumware. Sun CC utilise actuellement RogueWave, mais je crois
qu'il essaie d'évoluer dans un autre sens. G++ utilise
l'implémentation g++.

[...]
> pour l'anecdote:

> String& operator << (String& inString, long int32){
> static char temp[48];
> char* p = temp;
> ltoa(int32, p, inString.getRadix());
> register char sep = inString.getSep();
> if (sep){
> char cnt = (inString.getRadix() == 10) ? 3 : 2;
> char* frst = temp + (*temp == '-');
> char* curr = strchr(temp, '\0');
> p += sizeof(temp);
> *--p = 0;
> for (char in = 0; curr != frst; ++in){
> if (in == cnt)
> *--p = sep, in = 0;
> *--p = *--curr;
> }
> if (*temp == '-')
> *--p = '-';
> }
> return inString.append(p, ::strlen(p));
> }

> itoa / ltoa ne sont pas standards mais il existe de nbrx portages.

Tu as ça d'où ? Il faut se méfier de ce qu'on trouve sur
l'Internet -- 90%, sinon plus, c'est des efforts des amateurs
qui ne comprenent pas le problème ni les outils qu'ils essaient
à mettre en oeuvre. Ici, c'est manifestement le cas : l'auteur
est un amateur qui ne connaît ni les problèmes de formattage
internationnalisé, ni à vrai dire le C++, ni les principes de
base d'une bonne conception.

--
James Kanze kanze...@neuf.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Sylvain

unread,
Jul 9, 2006, 9:02:07 AM7/9/06
to
James Kanze wrote on 09/07/2006 14:09:
>
> > et des %, très mauvais les % !!
>
> Pourquoi ? Si les paramètres sont positifs, ils donnent un
> résultat précis.

ça devient trop facile de te pousser à te contredire, tu saisis la
moindre perche...

> un amateur qui ne connaît ni les problèmes de formattage
> internationnalisé, ni à vrai dire le C++, ni les principes de
> base d'une bonne conception.

les prétendus professionels qui ne savent même pas afficher un nombre en
arabe dans le texte m'ont également bcp amusé ! quant aux autres
généralités creuses, je suis las de les lire; pas envie d'y répondre,
juste de les plonker.

Sylvain.

Message has been deleted
0 new messages