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 :

Affichage de flottants dans la console : je deviens fou


Sujet :

C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut Affichage de flottants dans la console : je deviens fou
    Hello,

    Je dois afficher sur la console une série de flottants, en mimant plus ou moins un tableau.

    Disons qu'une "cellule" fasse 10 caractères. Je veux que le point décimal soit toujours affiché sur le caractère 4 (si on va de 0 à 9). Je souhaiter tronquer les décimales qui pourraient dépasser. A gauche de la virgule, je sais que j'aurai toujours assez de place.

    J'ai le nez dans le "The C++ Standard Library", j'essaye de jouer avec setw, setprecision, etc, mais je n'arrive pas à avoir ce que je veux. La logique de cette bibliothèque m'échappe totalement.

    PS : ce post devrait peut-être être déplace dans la section "SL & STL".

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Oui la doc n'est pas claire pour un novice en la matière. En général, je n'ai réussi à utiliser cette partie qu'en bricolant, en essayant quelques appels et en observants leurs effets. A force, on finit par trouver ce qu'on cherche.

    Note que ça touche aux locales et que les résultats de cette API peuvent dépendre de ta locale.
    Find me on github

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    J'ai l'impression qu'il est impossible de définir le nombre de chiffres avant et après le séparateur décimal.

    setpricesion() peut avoir deux effets :

    - si on utilise la notation décimale, c'est le nombre total de chiffres
    - si on utlise la notation exponentielle, c'est le nombre de chiffres après le séparateur décimal

    Mais, si on veut définir le nombre de chiffres après le séparateur tout en étant en mode décimal, on peut s'en sortir en rajoutant au flux fixed. Mais dans ce cas là, on se récupère les 0 superflus après le spérateur...

    Je ne sais pas ce qu'ils avaient picolé le jour où ils ont pondu ça, mais ça devait au moins être de l'alcool de patate arrangé aux doryphores.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Pour faire cela, tu as besoin de trois manipulateurs :

    setw(n) qui force la taille totale du champ (10 pour toi) pour la prochaine insertion dans le flux
    par défaut,
    il rajoute des blancs (tu peux customiser cela avec setfill())
    et aligne à droite (mais tu peux utiliser left pour aligner à gauche...)

    setprecision(n) : qui force le nombre de décimales (5 pour toi), c'est indépendant du type de notation, mais cela ne marche que pour les flottants, si tu lui passes des types entiers, il te les imprime sans décimale (c'est normal, un entier ça n'a pas de décimales). Une fois setprecision(5) fixé, tu auras 5 décimales jusqu'à nouvel ordre.

    fixed : qui force l'impression en notation décimale (c'est à dire sans exposant), jusqu'à nouvel ordre, aussi

    donc tu vas faire quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    double a=1.0,b=sqrt(2.0),c=1.0/3.0;
    // taille 10, six décimales, partie entière
    cout<<setprecision(5)<<fixed;
    cout<<setw(10)<<a;
    cout<<setw(10)<<b;
    cout<<setw(10)<<c;
    cout<<endl;
    Les manipulateurs (les flux en général), c'est un peu étrange au début, mais quand on s'y habitue, c'est carrément pratique... Certaines caractéristiques (par exemple le comportement différent de setw et de setprecision) paraissent étranges au début, mais on s'aperçoit vite que c'est très bien pensé...

    Francois
    Dernière modification par Invité ; 26/10/2011 à 21h32.

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Merci pour ce récapitulatif.

    Si je veux mes séparateurs décimaux alignés, je suis donc obligé d'afficher les zéros non significatifs...

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Ca oui, ou alors il faut remplir toi même le vide avec des espaces
    Find me on github

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Bon, ben je mets Résolu, mais le coeur n'y est pas...

  8. #8
    screetch
    Invité(e)
    Par défaut
    les flux c'est pas forcément le mieux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        printf("%10.5f\n", sqrtf(2.f));
        printf("%10.5f\n", sqrtf(1578017.f));
        printf("%10.5f\n", 10.f);
    donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       1.41421
    1256.19141
      10.00000
    (pour les explications: 10 est la taille de la colonne, .5 veut dire 5 chiffres apres la virgule. En comptant le '.', on aura donc 4 chiffres avant la virgule, la virgule, 5 chiffres apres la virgule)

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par screetch Voir le message
    les flux c'est pas forcément le mieux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        printf("%10.5f\n", sqrtf(2.f));
        printf("%10.5f\n", sqrtf(1578017.f));
        printf("%10.5f\n", 10.f);
    C'est exactement le même code que l'exemple avec les flux, à peu près de le même taille. En pratique, j'ai l'impression qu'on écrit l'un ou l'autre par habitude.

    Personnellement, je préfère les flux parce qu'ils traitent de manière uniforme l'impression et les fichiers, et qu'ils gèrent facilement les types utilisateurs (adapter operator<< à une nouvelle classe, c'est simple comme une surcharge).

    @oodini
    L'objet de l'alignement, dans le flux, c'est l'écriture de fichiers "en colonne fixe". Les flux savent donc aligner à gauche ou à droite, mais l'alignement au milieu, c'est étrange (dans ce contexte particulier d'écriture dans un flux).

    Tu peux faire ce que tu veux en bricolant un peu. Il faudrait aligner à droite, sur 3 positions, le signe et les dizaines de ton nombre, et à gauche, sur 7, les unités et décimales.

    Par exemple pour imprimer 11.1, tu ferais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double f=11.1;
    int gauche=((int) f)/10;
    double droite=f-10.0*gauche;
    cout<<setw(3)<<right<<gauche<<setw(7)<<left<<droite<<endl;
    Le code final sera plus compliqué, parce que tu vas devoir traiter 4 cas suivant que le nombre est positif ou négatif, et inférieur ou supérieur en valeur absolue à 10.

    Ce n'est pas d'une élégance folle, mais une fois intégré dans une petite fonction utilitaire, c'est probablement la solution la plus simple à ton problème.

    Francois

  10. #10
    screetch
    Invité(e)
    Par défaut
    je n'aime pas mettre un flag persistant dans cout pour afficher un float; et c'est pas forcément thread safe non plus.
    si tu avais du code qui restore l'état de cout a la rigueur?

  11. #11
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par screetch Voir le message
    je n'aime pas mettre un flag persistant dans cout pour afficher un float; et c'est pas forcément thread safe non plus.
    si tu avais du code qui restore l'état de cout a la rigueur?
    Ce que tu peux faire pour avoir une sorte de persistance, c'est tout simplement utiliser une autre fonction que std::cout, définie par toi et avec la même signature, qui balance le formatage voulu quand tu en as besoin. C'est une sorte de factorisation. Tu vois ou pas ?
    Find me on github

  12. #12
    screetch
    Invité(e)
    Par défaut
    plutot le contraire; ma remarque etait plutot:
    jusque quand est valable le << setprecision? le << fixed? le << setw?

  13. #13
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par screetch Voir le message
    plutot le contraire; ma remarque etait plutot:
    jusque quand est valable le << setprecision? le << fixed? le << setw?
    Qu'on m'arrête si je dis une bêtise, mais il me semble que c'est perdu dès qu'un nombre à été traité. Comme std::cout est une ressource potentiellement commune à des codes qui ne se connaissent pas, ça me paraît assez logique.
    Find me on github

  14. #14
    screetch
    Invité(e)
    Par défaut
    j'avoue ne pas avoir trouvé d'info a ce sujet, pour l'instant.
    cout est un objet global, ca marche comment en multithread?

  15. #15
    Invité
    Invité(e)
    Par défaut
    Je ne sais pas si les standards récents le prennent en compte, mais dans le passé, les specs STL et iostream ne disaient rien sur le multithread. Tout dépendait de l'implémentation.

    Quelques éléments de réponse quand même :

    Jusqu'à quand...

    Tous les manipulateurs sont "permanents", ce qui revient à dire qu'ils s'appliquent "jusqu'à nouvel ordre". La largeur de champ, width(), est la seule exception. Elle n'est valable qu'une fois (réinitialisé après chaque sortie). Ces propriétés sont gérées au niveau de l'objet iostream: si tu ferme ton stream et que tu en ouvres un autre (sur le même fichier, par exemple) tout est réinitialisé. En théorie, tu peux avoir plusieurs streams en même temps sur le même fichier, mais la synchronisation dépend (partiellement au moins) de l'implémentation...

    Dans un environnement multithread, pour écrire sur cout, le mieux est d'utiliser des stringstream, et des manipulateurs, pour faire le formatage, puis d'envoyer le résultat dans cout, avec aucun autre manipulateur que setw().

    L'utilisation de stringstream comme buffers de formatage est de toutes façons une bonne pratique quand tu as pas mal de sorties textes formatées.

    Francois

  16. #16
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    n3242, 27.2.3 (traduction libre)
    Les accès concurrents au flux (y compris les buffer) par différents threads peut conduire à des "data race" (donc UB), sauf spécification contraire (*).
    (*) C'est le cas des flux synchroniser avec les IO standard si je comprends bien la suite (à confirmer quand même).

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

Discussions similaires

  1. Affichage en colonne dans la console
    Par cyberps2 dans le forum Débuter
    Réponses: 6
    Dernier message: 09/05/2009, 19h25
  2. Affichage caractères unicodes dans la console
    Par boss_gama dans le forum C++
    Réponses: 18
    Dernier message: 05/03/2007, 18h27
  3. [log4J] affichage des log4J dans la console (texte bleu)
    Par lalie.perso dans le forum Logging
    Réponses: 1
    Dernier message: 13/04/2006, 13h52
  4. [TOMCAT][LOGS]pas d'affichage de trace dans la console
    Par fabszn dans le forum Tomcat et TomEE
    Réponses: 3
    Dernier message: 23/08/2005, 02h28
  5. Problème a l'affichage dans la console (printf)
    Par PhoneKilleR dans le forum C
    Réponses: 21
    Dernier message: 23/09/2003, 17h21

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