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 :

fonctionnement printf %f


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut fonctionnement printf %f
    Bonjour,

    J'ai fait quelques tests avec la fonction printf

    Si j'ai bien compris, une specification de conversion est sous la forme "%[flags][width][precision][len]type" :
    - Valeurs possibles de flags : '+', '#', 'espace', '-'.
    - width : nombre décimal ne commençant pas par '0'.
    - precision : nombre décimal précédé du caractère '.'. Si nombre à virgule, nombre decimal à afficher, sinon si %s, c'est la taille maximale de la chaine à afficher, sinon champ non pris en compte.
    - Valeurs possibles de len : "l", "ll", "L", "h", "hh", "z".
    - Valeurs possibles de type: '%', 'c', 's', 'i', 'd', 'u', 'x', 'X', 'p', 'f', 'F', 'e', 'E', 'g', 'G' (il en existe d'autres mais toutes ce sont pas supportées par la plupart des plateformes).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        printf("\"% 6.2f\"\r\n", 1.234); // affiche "  1.23"
        printf("\"% 3.2f\"\r\n", 1.234); // affiche " 1.23"
        printf("\"% 4.6f\"\r\n", -0.5);    // affiche " -0.500000"
    A quoi correspond le chiffre juste après le caractère espace ?
    => en lisant la documentation, j'avais l'impression que ça correspondait à la taille minimal de la chaine générée mais ce n'est pas ce qui est affiché :
    - sur la seconde ligne, il y a un espace en trop
    - sur la troisième ligne, il y a un espace en trop


    Aussi, pouvez-vous me confirmer que les cas suivants ont la même signification ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        // Même signification ?
        printf("\"% 6.2f\"\r\n", 1.234);
        printf("\"%6.2f\"\r\n", 1.234);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       // Même signification ?
        printf("\"% .2f\"\r\n", 1.234);
        printf("\"% 0.2f\"\r\n", 1.234);
        printf("\"% 01.2f\"\r\n", 1.234);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       // Même signification ?
        printf("\"%-0 6.2f\"\r\n", 1.234);
        printf("\"% 0-6.2f\"\r\n", 1.234);
    Pour moi, les règles sont les suivantes (dites moi si je me trompe) :
    - Le flag '-' est prioritaire sur le flag '0' qui est prioritaire sur le flag 'espace'.
    - Si pas de flag dans la séquence, le flag 'espace' est actif.
    - Si le champ width n'est pas défini, alors il vaut 1.
    - Le champ width ne peut pas être défini avec la valeur 0 car en conflit avec le flag '0'.
    - Le champ width désigne la taille minimale de la chaine généré, alors que le champ precision correspond au nombre de chiffres après la virgule


    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par boboss123 Voir le message
    A quoi correspond le chiffre juste après le caractère espace ?
    Comme dans "% 6f" ? C'est la taille maximale du chiffre à afficher (il sera alors écrit sur 6 caractères de l'écran avec espaces de complétion si pas assez de chiffres). Toutefois moi je ne mets jamais d'espace => "%6f".

    Citation Envoyé par boboss123 Voir le message
    Aussi, pouvez-vous me confirmer que les cas suivants ont la même signification ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        // Même signification ?
        printf("\"% 6.2f\"\r\n", 1.234);
        printf("\"%6.2f\"\r\n", 1.234);
    Oui. Accessoirement tu te ferais moins chier si tu remplaçais les guillemets par des crochets => printf("[% 6.2f]\n", 1.234)...
    Citation Envoyé par boboss123 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       // Même signification ?
        printf("\"% .2f\"\r\n", 1.234);
        printf("\"% 0.2f\"\r\n", 1.234);
        printf("\"% 01.2f\"\r\n", 1.234);
    Je présume (je me suis jamais posé ce genre de détails)

    Citation Envoyé par boboss123 Voir le message
    - Le champ width désigne la taille minimale de la chaine généré, alors que le champ precision correspond au nombre de chiffres après la virgule
    width désigne le nombre maximal de caractères utilisés pour afficher l'ensemble du nombre. Ce nombre inclut donc la partie entière, le point décimal et la précision. Donc 123.45 occupe 6 positions dont 2 décimaux et demandera donc "%6.2f" pour être affiché correctement.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Ok merci

    Citation Envoyé par Sve@r Voir le message
    width désigne le nombre maximal de caractères utilisés pour afficher l'ensemble du nombre. Ce nombre inclut donc la partie entière, le point décimal et la précision. Donc 123.45 occupe 6 positions dont 2 décimaux et demandera donc "%6.2f" pour être affiché correctement.
    Pourtant la ligne suivante affiche [12345.678000], ce qui est plus grand que 2 caractères :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("[%2f]\r\n", 12345.678);
    => c'est pourquoi je pense que "width" désigne le nombre minimale de caractères et non pas maximal.



    Pour la ligne suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("[% 3.2f]\r\n", 1.234);
    => ça devait m'afficher [1.23], non ? ... pourtant avec GNU GCC, j'ai [ 1.23] : c'est un bug ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Sinon, tu peux lire la doc.

    width description
    (number) Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.
    Oui si width est un nombre c'est le minimum de caractères à afficher. Si l'affichage est plus court, y'a le padding avec des espaces par défaut, ou avec le caractère de padding spécifié.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    ok merci (cette doc est plus précise que celles que j'avais trouvées)

    donc je confirme que les libraries pintf livrée avec GCC sont buguées... ce qui est bizarre

    D'ailleur, chez vous, la ligne suivante affiche quoi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("[%08.6u]\r\n", 12345);
    => ça m'affiche [ 012345] alors que pour moi, on devrait avoir [00012345] (c'est comme si le flag '0' n'était pas pris en compte)

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par boboss123 Voir le message
    => ça m'affiche [ 012345] alors que pour moi, on devrait avoir [00012345] (c'est comme si le flag '0' n'était pas pris en compte)
    Chez-moi, ça affiche [ 12345] (même pas de 0). Peut-être parce que tu emploies une notation dédiée aux flottants (width.precision) avec le flag "u" dédié aux entiers => comportement à mon avis indéterminé

    Si je reste en notation entière (printf("[%08u]\n", 12345)), j'obtiens bien [00012345]...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Chez-moi, ça affiche [ 12345] (même pas de 0). Peut-être parce que tu emploies une notation dédiée aux flottants (width.precision) avec le flag "u" dédié aux entiers => comportement à mon avis indéterminé
    Si je reste en notation entière (printf("[%08u]\n", 12345)), j'obtiens bien [00012345]...
    Dans le lien fourni par Bousk (http://www.cplusplus.com/reference/cstdio/printf/), il est bien défini un comportement pour la [precision] pour un entier. Dans ton cas, on dirait que ta fonction printf ne gère pas le champ [precision] pour les entiers et qu'en plus, lorsque le [flag] '0' est déclaré, que ça fait buguer ta fonction.
    => en C, j'ai l'impression qu'il n'existe pas de comportement standard pour la fonction printf ... donc pour avoir du code portable, il faut utiliser vraiment que les fonctions de base (même la gestion des arrondis d'un float a l'air de dépendre de l’implémentation de printf utilisée).

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par boboss123 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("[%08.6u]\r\n", 12345);
    => ça m'affiche [ 012345] alors que pour moi, on devrait avoir [00012345] (c'est comme si le flag '0' n'était pas pris en compte)
    Pourtant la doc est claire : le .precision avec u est le nombre minimum de chiffre qui sera affiché. Et si je compte bien tu as effectivement 6 chiffres avec le padding du 0.
    Puis tu lui demandes aussi d'afficher au moins 8 caractères et " 012345" a bien 8 caractères avec les 2 espaces de padding. Le 0 ayant été ajouté parce que tu demandes 6 chiffres et n'en fournis que 5, il est padding de precision et non de width.
    Si width faisait aussi un padding avec des 0, il y aurait conflit entre les 0 du padding du nombre et de l'output. Ils ont choisi d'ignorer le width.

    en C, j'ai l'impression qu'il n'existe pas de comportement standard pour la fonction printf
    Tout dépend de l'implémentation et tous les résultats présentés ici sont cohérents avec la doc et la norme.

    Utiliser la notation de précision avec des entiers est de toutes manière au moins une mauvaise idée.
    Si tu veux afficher un entier non signé, tu utilises %u.
    Si tu veux le padder avec des 0, tu utilises %0*u ou %.*u. Sachant que la première écriture est la plus commune et sera donc plus facilement comprise.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Pourtant la doc est claire : le .precision avec u est le nombre minimum de chiffre qui sera affiché. Et si je compte bien tu as effectivement 6 chiffres avec le padding du 0.
    Puis tu lui demandes aussi d'afficher au moins 8 caractères et " 012345" a bien 8 caractères avec les 2 espaces de padding. Le 0 ayant été ajouté parce que tu demandes 6 chiffres et n'en fournis que 5, il est padding de precision et non de width.
    Si width faisait aussi un padding avec des 0, il y aurait conflit entre les 0 du padding du nombre et de l'output. Ils ont choisi d'ignorer le width.
    Avec ma commande, je lui ai demandé deux trucs :
    - Le "08" indique que la chaine doit faire au moins huit caractères avec alignement à droite en utilisant le caractère '0' en padding
    - Le ".6" indique que la chaine doit faire au moins 6 caractères en utilisant le caractère '0' en padding
    => Donc pour moi, la chaine devrait être transformée de la manière suivante : "12345" => "012345" (pour le ".6") => "00012345" (pour le "08"). Donc en cas de conflit, mon printf semble ignorer le flag '0' au lieu de prendre la valeur la plus grande entre [length] et [.precision] (ce qui me semblait plus logique à faire). La doc n'est pas très précise à propos de la gestion sur ce type de conflit : donc conflit = cas indéterminé.
    => Dans le Cas de Svear, son printf ignore le flag '0' et le champ [.precision]

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

Discussions similaires

  1. printf command ne fonctionne pas pour retour à la ligne.
    Par mitchreward dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 21/02/2014, 13h17
  2. Réponses: 8
    Dernier message: 27/12/2011, 15h44
  3. Printf ne fonctionne plus
    Par Malikemal dans le forum Débuter
    Réponses: 18
    Dernier message: 14/06/2011, 19h37
  4. printf fonctionne pas sous Eclipse
    Par la_poupee_irradiee dans le forum Eclipse Java
    Réponses: 9
    Dernier message: 29/07/2009, 23h29
  5. [printf()] comment ca fonctionne
    Par pmartin8 dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 20/04/2006, 21h05

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