OVH Cloud OVH Cloud

écriture des nombres (formatage de sortie)

32 réponses
Avatar
KooK
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

10 réponses

1 2 3 4
Avatar
kanze
Arnaud Debaene wrote:
"Sylvain" a écrit dans le message de news:
44ad7f56$0$832$
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.

--
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


Avatar
kanze
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 ''. 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.

--
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


Avatar
kanze
Olivier Miakinen wrote:

[...]
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écima l.
</cit.>


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

--
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



Avatar
Sylvain
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.

Avatar
Sylvain
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.

Avatar
Sylvain
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, '');
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.

Avatar
Olivier Miakinen

(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

Avatar
James Kanze
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
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


Avatar
James Kanze
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
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

Avatar
Sylvain
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.

1 2 3 4