begin process at 2008 08 29 20:12:00
1 233 870 membres
392 nouveaux aujourd'hui
14 294 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

FORMATTEZ VOS CHAINES DE CARACTERES GRACE A LA FONCTION FORMAT


Information sur le tutorial

Catégorie :Tutoriaux Date de création : 29/11/2005 22:13:23 Vu : 14 444 fois

Note :
9,83 / 10 - par 6 personnes
9,83 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note

Description

Beaucoup de monde, debutants comme initiés, connaissent peu ou mal la fonction Format.

La fonction Format permet tout simplement de formatter une chaine de caracteres grace a des specificateurs de formatage.
Dans cette definition barbare, il faut comprendre que format est une fonction specialisée dans la convertion de differents type (réel, entier, pointeurs ect...) dans un texte humainement lisible.

Elle remplacerat donc parfaitement des fonctions tel que IntToStr, FloatToStr, IntToHex, que certains aiment mettre de part et d'autre dans leurs methode de convertions et qui ce soucis un minimum de l'optimisation et la claretée du code de ces dernieres.

Tutorial





Sommaire


____________ A) Quand utiliser Format ?
____________ A.Bis) Recomendations.
____________ B) Performances
____________ C) Déclaration de Format dans Delphi
____________ D) Qu'est-ce qu'une chaine de formatage ?
____________ E) Qu'est-ce qu'un spécificateur de format ?
____________ F) Tableau des types de spécificateurs de format
____________ G) Format flottant et séparateur décimal
____________ H) Ecriture des spécificateurs d'indice, taille etprécision
____________ Z) Conclusion





A) Quand utiliser Format ?

Utilisez format dés que vous desirez convertir une valeur en une chaine de caracteres.
En  effet, Format vas vous faciliter grandement la vie dans ce domaine,
en  remplaçant toutes les autres fonctions comme FloatToStr ou IntToStr...

Exemple (afficher les coordonnées de la souris sur le titre de la fiche en cours) :
   
    procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
    begin
       caption := 'x: '+IntToStr(X)+' | y: '+IntToStr(Y);
    end;


    Seras facilement remplaçable par :

    procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
    begin
      caption := format('x: %d | y: %d',[X, Y]);
    end;

Comme vous l'avez compris, Format est LA fonction spécialisée dans le formatage valeurs vers chaine.



A.Bis) Recomendations.


- Les chaines de formatage ne sont pas compilées dans Delphi, contrairement en C et C++. Verifiez donc bien le type des specificateurs de format que vous utiliserez pour eviter les erreurs d'execution.

- Pour les concatenations de chaines courtes (string et char), il est preferable de ne pas utiliser format, mais plutot la bonne vieille methode qui est la plus rapide, par exemple :

    SC := protocol+'://'+domainename+'/'; {au lieu de : SC := format('%s://%s/',[protocol,domainename]); }




B) Performances

Je vous le donne en mille, Format est plus rapide que la plupart des autres méthodes.
Parlons chiffres et millisecondes, avec un bench (test de performance) tout simple :
[test realisé sur un Athlon 1800+ a 1.5Ghz en parfaite condition de test]

    - 1er test :

        for X := 1 to 1000000 do s := 'X = ' + IntToStr(X);

        Résultat : Moyenne de 945 ms presque 1 seconde.

    - 2eme test :

        for X := 1 to 1000000 do s := format('X = %d',[X]);

        Résultat : Moyenne de 532 ms presque 1/2 seconde.

(j'ai refait ce test plusieurs fois pour etre sur et certain de ce que j'avance maintenant)
Format affiche de meilleures performance et vous permettras d'optimiser  correctement
vos programmes, surtout sur les méthodes de conversion et  d'affichage de texte.





C) Déclaration de Format dans Delphi

Format est déclarée dans l'unité SysUtils de Delphi.

(Format fait appel a FmtStr(); incluse elle aussi dans l'unité SysUtils.)

Elle se présente de cette manière :

    function Format(const Format: string; const Args: array of const): string;
    begin
      FmtStr(Result, Format, Args);
    end;

    function Format(const Format: string; const Args: array of const;
                 const FormatSettings: TFormatSettings): string;
    begin
        FmtStr(Result, Format, Args, FormatSettings);
    end;

const Format correspond à la chaine de format, elle  contient le texte et
        les spécificateurs de format de cette dernière.
const Args correspond au tableau d'arguments à appliquer aux
        spécificateurs de format contenus dans  la chaine de formatage.
const FormatSettings correspond  aux parametres des variables globales. 





D) Qu'est-ce qu'une chaine de formatage ?

Une chaine de formatage est tout simplement une chaine qui contient d'une part
du texte
et d'autre part des spécificateurs de format.





E) Qu'est-ce qu'un spécificateur de format ?

Un spécificateur de format est un "marqueur" qui permet d'identifier le type et les paramètres
de traitement d'un argument à formater dans une chaine de format.

Dans Delphi comme dans C++, un spécificateur de format commence toujours par le symbole "%".
Il est donc logique que le caractères % (pour afficher un pourcentage par exemple) s'obtiens donc
en le doublant comme ceci "%%" (a l'instar d'un double ' ' dans une chaine string).
Exemple :

    format('le rapport est de : %.2f %%',[rapport]);


Les spécificateurs de format ont la forme suivante : (tiré de l'aide Delphi)

    "%"[index ":"]["-"][largeur]["."prec]type

Comme dit plus haut, Le spécificateur de format commence toujours par le symbole %,
il sera suivis ensuite de divers paramètres (dans l'ordre) :

   [index ":"]  correspond a l'index de l'argument dans le tableau d'arguments (facultatif)
   ["-"]        correspond a l'alignement par défaut a gauche (facultatif)
   [largeur]    correspond a la taille (facultatif)
   ["." prec]   correspond a la précision (facultatif)
   type         correspond au type de l'argument à convertir (obligatoire)
                (Provoquerasune erreur de conversion si l'argument n'est pas de ce type)

Index, Largeur et Précision doivent être de type entier.




F) Tableau des types de spécificateurs de format

__| %d |____________________________________________

    Entiers signés.


    Types supportés : integer, smallint, shortint, longint, byte, word, int64, cardinal.

Si le spécificateur de précision est défini, la chaine en sortie sera remplie de zéro
si la taille de l'entier est inferieure à celle de la précision.

Exemple:
        format('mon chiffre est : %.4d', [12]);       
    renvois "mon chiffre est : 0012"
 

__| %u |____________________________________________

    Entiers non-signés.
(valeur absolue)

Identique à %d mais sans retour de signe.

%u est equivalant a : format( '%d', [abs(var)]);
 

__| %e |____________________________________________

    Réel signé. (écriture scientifique)

    Types supportés : single, real, real48, double, comp, extended, currency.

La valeur est convertie en une chaîne de la forme "-d.ddd...E+ddd".

Le nombre total de chiffres dans la chaîne résultante (y compris celui qui précède la virgule)
est donné par le spécificateur de précision dans la chaîne de format.
Si celui-ci est omis, une précision de 15 est prise en compte par défaut.

Le caractère "E" dans la chaîne résultante esttoujours suivi d'un signe "+" ou "-",
puis de trois chiffres au moins.

 
__| %f |____________________________________________

    Réel signé.

    Types supportés : single, real, real48, double, comp, extended, currency.

Définissez un spécificateur de précision pour définir le nombre de chiffres
après la virgule.

Exemple :
        format('Pi = %.4f', [pi]);   
    renvois "Pi = 3,1415"

        format('Pi = %.0f', [pi]);  
 
    renvois "Pi = 3"
 

__| %g |____________________________________________

    Réel signé. (au plus court)

    Types supportés : single, real, real48, double, comp, extended, currency.

La valeur est convertie en une chaîne décimale la plus courte possible en
utilisant le format fixe ou scientifique.

Le nombre de chiffres significatifs dans la chaîne résultante est fourni par
le spécificateur de précision dans la chaîne de format :
une précision par défaut de 15 est prise en compte si le spécificateur de précision
est omis.

Les caractères zéro sont supprimés de la fin de la chaîne résultante et
la virgule décimale n'apparaît que si elle est nécessaire.

La chaîne résultante utilise le format fixe si le nombre de chiffres à gauche de
la virgule est inférieur ou égal à la précision indiquée et si la valeur est supérieure
ou égale à 0,00001. Sinon, la chaîne résultante fait appel au format scientifique.

 
__| %n |____________________________________________

    Réel signé. (avec séparateur des milliers)
    Entier signé. (voir la note)

    Types supportés : single, real, real48, double, comp, extended, currency.

Numérique L'argument doit être une valeur flottante.La valeur est convertie en
une chaîne de la forme"-d,ddd,ddd.ddd...". Le format "n" correspond au
format "f", sauf que la chaîne résultante contient le séparateur des milliers.

Exemple :
        format('%n', [10248.125]);
    renvois "10 248,125"

_____| NOTE |_____

    Types : integer, smallint, shortint, longint, byte, word, int64, cardinal.

Pour ces types vous devrez écrire format de cette façon :

        format('%.0n', [VarInt / 1]);

Exemple :
        format('Taille : %.0n octets', [24533126/1]);
    renvois "Taille : 24 533 126 octets"


__| %m |____________________________________________

    Réel signé. (représentation monétaire)

    Types supportés : single, real, real48, double, comp, extended, currency.

La valeur est convertie en une chaîne représentant une valeur monétaire.

La conversion est contrôlée par les variables globales CurrencyString,
CurrencyFormat
, NegCurrFormat,ThousandSeparator, DecimalSeparator
et CurrencyDecimals ou leur équivalent dans une structure de données
TFormatSettings
.

Si la chaîne de format contient un spécificateur deprécision, il remplace
la valeur envoyée par la variable globaleCurrencyDecimals ou
son équivalent TFormatSettings.

Exemple :
        CurrencyString := '€';
        format('Francs en Euros : %.5m', [100 / 6.55957]);

    renvois "Francs en Euros : 15,24490 €"

        CurrencyString := 'Fr';
        format('Euros en Francs : %.2m', [15.24490 * 6.55957]);

    renvois "Euros en Francs :  100,00 Fr"


__| %p |____________________________________________

    Pointeur.

    Types supportés : (^Type), PAnsiString, PString,PByteArray, PCurrency,
                                   PDouble, PExtended, PSingle, Pinteger,POleVariant,
                                   PShortString, PTextBuf, PVarRec, PVariant, PWideString,
                                   PWordArray.


La valeur est convertie en une chaîne de 8caractères (32bits) qui représente
des valeurs de pointeur enhexadécimal.

Exemple :
        format('%p', [PInteger(1024)]);
    renvois "00000400"


__| %s |____________________________________________

    Chaîne.

    Types supportés : String, Char, PChar, AnsiString, WideString, ShortString.
 
La chaîne ou le caractère est inséré à la place du spécificateur de format.

Définissez le spécificateur de précision pour  indiquer la taille maximale de
la chaine, qui sera alors tronquée  automatiquement si elle est plus grande.

Exemple :
        format('nom : %s, prénom : %s', [edit1.text, edit2.text]);
    renvois "nom : Borland, prénom : Delphi"


__| %x |____________________________________________

    Hexadécimal.

    Types supportés : integer, smallint, shortint, longint, byte, word, int64, cardinal.

La valeur est convertie en sa représentation hexadécimale.

Si la chaîne de format contient un spécificateur deprécision, ce dernier spécifie
que la chaîne doit contenir au moins le  nombre indiqué de chiffres; si cela
n'est pas le cas, des caractères  zéro de remplissage sont rajoutés dans
la partie gauche de la chaîne.

Exemple :
        format('Char : #%0:.3d | Hexa : %0:.2x', [ord(' ')]);
    renvois "Char : #032 | Hexa : 20"




G) Format flottant et séparateur décimal

"Quelque soit le format flottant, les deux  caractères utilisés comme  séparateur décimal
et séparateur des milliers  sont respectivement  définis par les variables globales
DecimalSeparator  et ThousandSeparator  ou leur équivalent TFormatSettings."


Il faut comprendre par la, qu'en assignant une nouvelle valeur a ces variables globales,
on peu  modifier l'aspect d'affichage mais également  de réceptions des valeurs
de type flottant.

Un exemple concret de cette méthode est par exemple la réception d'un 
chiffre à virgule dans une boite d'édition (TEdit). L'utilisateur peut soit
mettre un point, soit mettre une  virgule
pour définir le séparateur décimal.
Afin d'éviter le declenchement d'une exception de conversion, il nous faut écrire
une  méthode simple pour savoir si nous sommes en  présence d'un point
ou  d'une virgule comme séparateur de décimales.
Exemple :

    if pos('.',edit1.text) > 0 then DecimalSeparator := '.'
    else
    if pos(',',edit1.text) > 0 then DecimalSeparator := ',';

Cette méthode influera directement  sur toutes les fonctions de  conversion
Flottant vers Chaine et  inversement, tel Format, FloatToStr,FloatToStrDef,
StrToFloat etc....

Après traitement, nous pourrons réassigner à DecimalSeparator,
une  valeur par défaut (virgule par exemple) et afficher les résultats
en  conséquence :

    DecimalSeparator := ',';
    Label1.caption   := Format('mon resultat est : %.2n',[resultat]);





H) Ecriture des spécificateurs d'indice, taille et précision

 "Les spécificateurs d'indice, de taille et de précision peuvent être directement
spécifiés en utilisant des chaînes contenant des chiffres décimaux
(par exemple "%10d") ou indirectement, en utilisant le caractère astérisque
(par exemple "%*.*f"). Lorsquevous utilisez l'astérisque, l'argument suivant
dans la liste (qui doit être obligatoirement une valeur entière) devient
la valeur effectivement utilisée".


Exemple :

    format('%.*f',[precision, chiffre]);

Dans cet exemple, le caractère * sera remplacer par le chiffre "precision".
Retenez bien cette méthode, car elle vous évitera de déclarer plusieurs
constantes de chaine de format et donc permettra encore une fois d'alléger
votre code.

Voici un exemple de ce qu'il ne faudrait pas faire :

    Function MavaleurToStr(const val: single; const Precision: byte = 0) : string;
    const
       Precision0 := '%.0f';
       Precision2 := '%.2f';
       Precision4 := '%.4f';
    Begin
      case Precision of
        0 : CDF := Precision0;
        1 : CDF := Precision2;
        2 : CDF := Precision4;
      end;
      result := format(CDF,[val]);
    end;

(PS: ne rigolez pas, j'ai déjà vus ce genre de code dans des programmes
pourtant sérieux. Ce qui démontre bien le manque de connaissance vis à vis
de la fonction Format).


Voici maintenant la bonne version de la méthode :

    Function MavaleurToStr(const val: single; const Precision: byte = 0) : string;
    Begin
      result := format('%.*f',[Precision, val]);
    end;

On peu bien sur utiliser "*" pour l'indice de l'argument exemple :
   
    Type
        TColor3h = record
            Red, Green, Blue : byte;
        end;
        TColorVl = (cvAll, cvRed, cvGreen, cvBlue);

    Function RGBStrHex(const RGB: TColor3h; const color : TColorVl = cvAll) : string;
    Begin
        // si on ne precise pas de couleur en particulier
        if color <> cvAll then
           // on renvois la couleur selon l'indice (ord) de color dans le type TColorvl
           // format recupere ce chiffre comme indice dans le tableau d'arguments
           // et nous renvois donc la couleur desirée

           result := format('%*:.2x',[ord(color), RGB.Red, RGB.Green, RGB.Blue])
        else
           // sinon, on renvois tout...
           result := format('%.2x%.2x%.2x',[RGB.Red, RGB.Green, RGB.Blue])
    end;

Dans cette fonction, on raccourcit radicalement le code, ce qui évite de faire
des cascade de IF ... ELSE ou de CASE ... OF.
La méthode devient alors simple et rapide, tout cela encore, grâce à Format.





Z) Conclusion

Voila, ce tuto sur la fonction format est finit.

Vous pouvez en retenir que :

    - Format est la solution la plus pratique pour convertir une valeur en
      une chaine de caractères.

    - Format est deux fois plus rapide que les méthodes :
   Chaine = SousChaine + "type"ToStr(valeur).

    - Format permet de réduire considérablement le code des diverses
      méthodes de conversion vers chaine decaractères.

    - Format rentre complètement dans le cadre "optimisation" des
      programmes.





29 novembre 2005 22:48:07 :
reglage d'un petit probleme de mise en page...
30 novembre 2005 14:49:52 :
diverses corrections de fautes et presentation.
15 janvier 2006 03:25:00 :
ajout du chapitre A.Bis (recomendations)
  • signaler à un administrateur
    Commentaire de f0xi le 02/12/2005 15:35:31 administrateur CS

    Excusez pour la presentation mais la page ne semble pas vouloir se rafraichir (chez moi du moins) et reste avec l'ancienne presentation ... etrange comme bug.

  • signaler à un administrateur
    Commentaire de f0xi le 02/12/2005 15:36:32 administrateur CS

    ha! ben voila il suffisait de poster un commentaire pour rafraichir la page ... logique... :X

  • signaler à un administrateur
    Commentaire de speletux le 18/12/2005 00:21:39

    Précision importante:

    La chaine de format n'est PAS COMPILEE (comme en C ou C++) mais interprétée.

    Une mauvaise chaîne de format passera très bien à la compilation mais le programme signalera une erreur à l'exécution au droit de l'appel à la fonction de formatage utilisant cette chaine.

  • signaler à un administrateur
    Commentaire de f0xi le 31/12/2005 22:07:49 administrateur CS

    tout a fait Speletux!

    une chaine de format dont le type est erroné (integer (d) a la place string (s)) provoqueras une erreur d'execution.

    il faut donc bien verifier et bien tester son programme (qu'on utilise format ou pas de toute façon, il faut toujours tout tester).

    mais, pas d'inquietude a avoir, une erreur de type serat vite decouverte dés qu'on appeleras la fonction et la retrouver devrais egalement etre un jeux d'enfant.

  • signaler à un administrateur
    Commentaire de f0xi le 15/01/2006 03:26:18 administrateur CS

    ajout d'un nouveau chapitre dans le tuto (A.Bis)

  • signaler à un administrateur
    Commentaire de betula le 17/02/2008 18:43:55

    Ce tutoriel est excellent.
    J'ajoute l'élément suivant qui peut compléter le chapître G:
    Il est possible d'utiliser une variable locale pour spécifier le séparateur de millier ou le séparateur décimale.

    Voici un exemple

    procedure AfficheEntierFormate;
    var
    i:integer;
    setting:Tformatsettings;
    begin
    i:=10000000;

    //première forme de l'utilisation de la fonction format
    //L'astuce consiste à diviser l'entier par 1 pour obtenir un nombre flottant
    //et utiliser le caractère de type de conversion n ('%.0n')
    //On affiche donc une nombre flottant sans afficher les décimales
    //La fonction format utilisera les paramètres locaux pour formater le nombre
    showmessage(format('le nombre est %.0n ',[i/1]));
    //Si le séparateur de millier est l'espace notre valeur sera 10 000 000

    //Si on désire contrôler les paramètres de formatage, il faut déclarer une variable
    //de type Tformatsetting et utiliser la deuxième forme de la fonction format
    //On initialise notre variable avec les paramètres régionaux fixés par l'usager
    GetLocaleFormatSettings(SysLocale.DefaultLCID, setting);
    //On modifie la valeur ou les valeurs qui nous intéressent
    setting.ThousandSeparator:=',';
    showmessage(format('le nombre est %.0n ',[i/1], setting));
    //Notre valeur sera affichée à coup sur selon notre désir 10,000,000

    end;

    De cette façon on ne modifie pas les variables globales et on ne risque pas d'effet de bord dans les traitements subséquents.

    Salutations
    BeTuLa

Ajouter un commentaire

Pub



Appels d'offres

Recherche developpeur ...
Budget : 700€
SITE MARCHAND LOCATION...
Budget : 3 000€
SITE MARCHAND POUR HOTEL
Budget : 4 000€

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

Boutique

Boutique de goodies CodeS-SourceS