Cours complet pour apprendre à programmer en D


précédentsommairesuivant

29. Sortie formatée

Ce chapitre traite des fonctionnalités du module std.format de Phobos, et non des fonctionnalités du langage D lui-même. Les indicateurs de formatage d'entrée et de sortie du D sont similaires à ceux du C. Avant d'aller plus loin, je voudrais résumer ici les indicateurs de format et les drapeaux :

Drapeaux

(peuvent être combinés)

-

aligner à gauche

+

afficher le signe

#

afficher d'une autre manière

0

compléter avec des zéros

espace

compléter avec des espaces

Indicateurs de format

 

s

par défaut

b

binaire

d

décimal

o

octal

x,X

hexadécimal

e,E

écriture scientifique

f,F

virgule flottante

g,G

comme e ou f

a,A

virgule flottante hexadécimal

Nous avons utilisé des fonctions comme writeln avec de multiples paramètres si nécessaire. Les paramètres sont alors convertis vers leur représentation en chaîne de caractères et envoyés vers la sortie.

Parfois, ce n'est pas suffisant. La sortie peut devoir suivre un certain format. Jetons un œil sur le code suivant, utilisé pour afficher les éléments d'une facture :

 
Sélectionnez
éléments ~= 1.23;
éléments ~= 45.6;
 
for (int i = 0; i != éléments.length; ++i) {
   writeln("Élément ", i + 1, " : ", éléments[i]);
}

La sortie :

 
Sélectionnez
Élément 1 : 1.23
Élément 2 : 45.6

L'information est correcte. Cependant, il est parfois souhaitable d'avoir un format de sortie différent. Par exemple, on pourrait vouloir qu'il y ait toujours deux chiffres après la virgule et que les points soient alignés, comme dans la sortie suivante :

 
Sélectionnez
Élément 1 :      1.23
Élément 2 :     45.60

Dans de tels cas, la sortie formatée se révèle utile. Les fonctions de sortie que nous avons vues jusqu'à maintenant ont des équivalents contenant la lettre f, pour « formaté », dans leur nom : writef() et writefln(). Le premier paramètre de ces fonctions est une chaîne de formatage qui décrit comment les autres paramètres doivent être affichés.

Par exemple, la chaîne de formatage qui ferait afficher la sortie souhaitée ci-dessus à writefln() est la suivante :

 
Sélectionnez
writefln("Élément %d : %9.02f", i + 1, éléments[i]);

La chaîne de formatage contient des caractères normaux qui sont affichés tels quels, ainsi que des indicateurs de format spéciaux qui correspondent à chaque paramètre à afficher. Les indicateurs de format commencent par le caractère % et finissent par un caractère de formatage. La chaîne de formatage ci-dessus contient deux indicateurs de format : %d et %9.02f.

Chaque indicateur est associé aux paramètres qui suivent dans l'ordre. Par exemple, %d est associé avec i+1 et %9.02f est associé avec éléments[i]. Chaque indicateur donne le format du paramètre auquel il correspond (les indicateurs de format peuvent également avoir des paramètres numériques ; nous verrons cela plus loin dans le chapitre).

Tous les autres caractères de la chaîne de format qui ne font pas partie d'un indicateur de format sont affichés tels quels. Ils correspondent aux caractères surlignés dans la chaîne suivante : « Élément %d:%9.02f ».

Les indicateurs de format comportent six parties, la plupart étant optionnelles. La partie nommée position sera expliquée un peu plus tard. Les cinq autres parties sont les suivantes (note : les espaces entre ces parties sont insérés ici pour des raisons de lisibilité, ils ne font pas partie des indicateurs) :

% drapeaux largeur précision caractère_de_formatage

Le caractère % au début et le caractère de formatage à la fin sont requis, les autres sont optionnels.

Du fait que % a une signification spécifique dans les chaînes de formatage, quand un % doit être affiché, il doit être écrit comme ceci : %%.

29-1. Caractères de formatage

  • b : le paramètre entier est affiché dans le système binaire.
  • o : le paramètre entier est affiché dans le système octal.
  • x et X : le paramètre entier est affiché dans le système hexadécimal ; avec des minuscules pour x et des majuscules pour X.
  • d : le paramètre entier est affiché dans le système décimal ; un signe négatif est également affiché s'il s'agit d'un type signé et que la valeur est strictement négative.

     
    Sélectionnez
    int valeur = 12;
     
    writefln("Binaire     : %b", valeur);
    writefln("Octal       : %o", valeur);
    writefln("Hexadécimal : %x", valeur);
    writefln("Décimal     : %d", valeur);
  • Sortie :
 
Sélectionnez
Binaire     : 1100
Octal       : 14
Hexadécimal : c
Décimal     : 12
  • e : le paramètre flottant est affiché selon les règles suivantes :

    • un seul chiffre avant le point ;
    • un point si la précision n'est pas nulle ;
    • des chiffres après le point, en nombre déterminé par la précision (6 par défaut) ;
    • le caractère e (signifiant « 10 puissance ») ;
    • le signe + ou -, selon si l'exposant est plus grand ou plus petit que zéro ;
    • l'exposant, constitué d'au moins deux chiffres.
  • E : pareil que e, sauf que le caractère E est affiché à la place de e.
  • f et F : le paramètre flottant est affiché dans le système décimal ; il y a au moins un chiffre avant le point et la précision par défaut est 6.
  • g : pareil que f si l'exposant est entre -5 et la précision ; sinon pareil que e. La précision n'indique pas le nombre de chiffres après le point, mais les chiffres significatifs de la valeur complète. S'il n'y a pas de chiffres significatifs après le point, le point n'est pas affiché. Les zéros les plus à droite après le point ne sont pas affichés.
  • G : pareil que pour g mais avec E ou F.
  • a : le paramètre en virgule flottante est affiché dans le format flottant hexadécimal :

    • les caractères 0x ;
    • un seul chiffre hexadécimal ;
    • le point si la précision n'est pas nulle ;
    • les chiffres après le point, dont le nombre est déterminé par la précision ; si la précision est indiquée, il y a autant de chiffres que nécessaire ;
    • le caractère p (signifiant « 2 puissance ») ;
    • le caractère + ou - selon si l'exposant est plus grand ou plus petit que zéro ;
    • l'exposant consistant en au moins un chiffre (l'exposant de la valeur 0 est 0).
  • A : pareil que a, mais avec 0X et P.

     
    Sélectionnez
    double valeur = 123.456789;
     
    writefln("avec e : %e", valeur);
    writefln("avec f : %f", valeur);
    writefln("avec g : %g", valeur);
    writefln("avec a : %a", valeur);
  • Sortie :
 
Sélectionnez
avec e : 1.234568e+02
avec f : 123.456789
avec g : 123.457
avec a : 0x1.edd3c07ee0b0bp+6
  • s : la valeur est affichée de la même manière que dans une sortie non formatée, selon le type de paramètre :

    • les valeurs booléennes comme true ou false ;
    • les valeurs entières comme avec %d ;
    • les valeurs en virgule flottante comme avec %g ;
    • les chaînes codées en UTF-8 ; la précision détermine le nombre maximal d'octets à utiliser (souvenez-vous que dans le codage UTF-8, le nombre d'octets n'est pas le même que le nombre de caractères ; par exemple la chaîne "ağ" a deux caractères consistant en un total de trois octets) ;
    • les structures et les classes comme le retour de la fonction toString() de leur type ; la précision détermine le nombre maximal d'octets à utiliser ;
    • les tableaux avec leurs éléments côte à côte.

       
      Sélectionnez
      bool b = true;
      int i = 365;
      double d = 9.87;
      string s = "formatée";
      auto o = File("fichier_test", "r");
      int[] a = [ 2, 4, 6, 8 ];
       
      writefln("booléen : %s", b);
      writefln("entier  : %s", i);
      writefln("double  : %s", d);
      writefln("chaîne  : %s", s);
      writefln("objet   : %s", o);
      writefln("tableau : %s", a);
    • Sortie :
 
Sélectionnez
booléen : true
entier  : 365
double  : 9.87
chaîne  : formatée
objet   : File(55738FA0)
tableau : [2, 4, 6, 8]

29-2. Largeur

Cette partie détermine la largeur du champ dans lequel le paramètre est affiché. Si la largeur est indiquée avec le caractère *, alors c'est le paramètre suivant qui indique cette largeur. Si la largeur est une valeur négative, le drapeau - est implicite.

 
Sélectionnez
int valeur = 100;
 
writefln("Dans un champ de 10 caractères : %10s", valeur);
writefln("Dans un champ de 5 caractères  : %5s", valeur);

Sortie :

 
Sélectionnez
Dans un champ de 10 caractères :        100
Dans un champ de 5 caractères  :   100

29-3. Précision

La précision est indiquée après le point dans l'indicateur de format. Pour les types en virgule flottante, elle détermine la précision de la représentation des valeurs. Si la précision est indiquée par le caractère *, la précision est obtenue à partir du paramètre suivant (ce paramètre doit être un int). Les précisions négatives sont ignorées.

 
Sélectionnez
double valeur = 1234.56789;
 
writefln("%.8g", valeur);
writefln("%.3g", valeur);
writefln("%.8f", valeur);
writefln("%.3f", valeur);

Sortie :

 
Sélectionnez
1234.5679
1.23e+03
1234.56789000
1234.568
 
Sélectionnez
auto nombre = 0.123456789;
writefln("Nombre : %.*g", 4, nombre);

Sortie :

 
Sélectionnez
Nombre : 0.1235

29-4. Drapeaux

On peut indiquer plus d'un drapeau à la fois.

  • - : la valeur est alignée à gauche dans son champ ; ce drapeau annule le drapeau 0.

     
    Sélectionnez
    int valeur = 123;
     
    writefln("Normalement aligné à droite : |%10d|", valeur);
    writefln("Aligné à gauche             : |%-10d|", valeur);
  • Sortie :
 
Sélectionnez
Pas d'effet sur les valeurs négatives : -50
Valeur positive avec le drapeau +     : +50
Valeur positive sans le drapeau +     : 50
  • + : si la valeur est positive, elle est préfixée par le caractère + ; ce drapeau annule le drapeau espace.

     
    Sélectionnez
    writefln("Pas d'effet sur les valeurs négatives : %+d", -50);
    writefln("Valeur positive avec le drapeau +     : %+d", 50);
    writefln("Valeur positive sans le drapeau +     : %d", 50);
  • Sortie :
 
Sélectionnez
Pas d'effet sur les valeurs négatives : -50
Valeur positive avec le drapeau +     : +50
Valeur positive sans le drapeau +     : 50
  • # : affiche la valeur sous une autre forme, selon caractère_de_formatage.

    • o : le premier caractère de la valeur octale est toujours 0 ;
    • x et X : si la valeur n'est pas zéro, elle est préfixée avec 0x ou 0X ;
    • virgules flottantes : un point est affiché même s'il n'y a pas de chiffres significatifs après le point ;
    • g et G : même les zéros non significatifs après le point sont affichés.

       
      Sélectionnez
      writefln("L'octal commence par un 0        : %#o", 1000);
      writefln("L'hexadécimal commence par 0x    : %#x", 1000);
      writefln("Un point même si non nécessaire  : %#g", 1f);
      writefln("Les zéros à droite sont affichés : %#g", 1.2);
    • Sortie :
 
Sélectionnez
L`octal commence par un 0        : 01750
L'hexadécimal commence par 0x    : 0x3e8
Un point même si non nécessaire  : 1.00000
Les zéros à droite sont affichés : 1.20000
  • 0 : le champ est complété avec des zéros (sauf si la valeur est nan ou infinity) ; si la précision est également indiquée, ce drapeau est ignoré.

     
    Sélectionnez
    writefln("Dans un champ de 8 caractères : %08d", 42);
  • Sortie :
 
Sélectionnez
Dans un champ de 8 caractères : 00000042
  • caractère espace : si la valeur est positive, un caractère espace est préfixé pour aligner les valeurs négatives et positives.
 
Sélectionnez
writefln("Pas d'effet sur les valeurs négatives : % d", -34);
writefln("Valeur positive avec un espace        : % d", 56);
writefln("Valeur positive sans espace           : %d", 56);
  1. Sortie :
 
Sélectionnez
Pas d`effet sur les valeurs négatives : -34
Valeur positive avec un espace        :  56
Valeur positive sans espace           : 56

29-5. Paramètres de position

Nous avons vu ci-dessus que les paramètres sont associés un à un avec les indicateurs dans la chaîne de formatage. Il est possible d'utiliser des numéros de position dans les indicateurs de format. Ceci permet d'associer des indicateurs avec des paramètres spécifiques. Les paramètres sont numérotés de façon croissante, en commençant par un 1. Les numéros de paramètres sont indiqués juste après le caractère %, suivi d'un $ :

 
Sélectionnez
%   position$   drapeaux   largeur   précision   caractère_de_formatage

Un avantage des paramètres de position est d'utiliser le même paramètre à plusieurs endroits dans la même chaîne de formatage :

 
Sélectionnez
writefln("%1$d %1$x %1$o %1$b", 42);

La chaîne de formatage utilise le paramètre numéro 1 dans quatre indicateurs différents pour l'afficher en formats décimal, hexadécimal, octal et binaire :

 
Sélectionnez
42 2a 52 101010

Une autre application de ces paramètres de position est de prendre en charge plusieurs langues. Lorsqu'ils sont référés par des numéros de position, les paramètres peuvent être déplacés n'importe où avec une chaîne de formatage spécifique à une langue. Par exemple, le nombre d'étudiants d'une classe peut être affiché de cette manière :

 
Sélectionnez
writefln("Il y a %s étudiants dans la classe %s.", nombre, classe);

Sortie :

 
Sélectionnez
Il y a 20 étudiants dans la classe 1A.

Supposons que le programme doive aussi prendre en charge le turc. La chaîne de formatage doit alors être choisie en fonction de la langue choisie. La méthode suivante utilise l'opérateur ternaire :

 
Sélectionnez
auto format = (langue == "fr"
               ? "Il y a %s étudiants dans la classe %s."
               : "%s sınıfında %s öğrenci var.");
 
writefln(format, nombre, classe);

Malheureusement, quand les paramètres sont associés un à un, la classe et le nombre d'étudiants sont inversés dans le message turc ; la classe s'affiche là où le nombre devrait être et inversement :

 
Sélectionnez
20 sınıfında 1A öğrenci var.   ← Faux : signifie "classe 20", et "1A étudiants" !

Pour éviter cela, les paramètres peuvent être indiqués par leur position pour associer chaque indicateur avec le bon paramètre :

 
Sélectionnez
auto format = (langue == "fr"
               ? "Il y a %s étudiants dans la classe %s."
               : "%2$s sınıfında %1$s öğrenci var.");
 
writefln(format, nombre, classe);

Maintenant, les paramètres apparaissent dans le bon ordre, indépendamment de la langue choisie :

 
Sélectionnez
Il y a 20 étudiants dans la pièce 1A.
 
1A sınıfında 20 öğrenci var.

29-6. format

La sortie formatée est également utilisable avec la fonction format() du module std.string. format() fonctionne de la même manière que writef() mais retourne le résultat dans une chaîne au lieu de l'afficher :

 
Sélectionnez
import std.stdio;
import std.string;
 
void main()
{
   write("Quel est ton nom ? ");
   auto nom = chomp(readln());
 
   auto resultat = format("Bonjour %s!", nom);
}

Le programme pourra utiliser ce résultat plus tard.

29-7. Exercices

  1. Écrire un programme qui lit une valeur et qui l'affiche dans le système hexadécimal.
  2. Écrire un programme qui lit une valeur flottante et qui l'affiche comme un pourcentage avec deux chiffres après le point. Par exemple, si la valeur est 1.2345, il devrait afficher 1.23 %.

Les solutionsSortie formatée - Correction.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+