Chiffres en lettres et récursivité

Soyez le premier à donner votre avis sur cette source.

Vue 8 358 fois - Téléchargée 916 fois

Description

Ce n'est pas la première source du genre mais juste une autre façon d'aborder la question en mettant en oeuvre la récursivité.
Facilement extensible, ce code avait, à l'origine, pour seul but de transformer sous forme littérale une année fournie en chiffres.
Limitations :
La fonction Int2Letters ne gère donc pas de décimales et ne traite que les nombres de quatre chiffres au maximum.
Mise en oeuvre de la surcharge de fonctions(voir annotations plus bas).

Source / Exemple :


{-----------------------------------------------------------------------------
 Unit Name: ChiffresEnLettres
 Author:    delphiprog
 Purpose:   convertir un nombre entier en toutes lettres en utilisant
            la récursivité. La fonction Int2Letters n'est pas transposable
            dans d'autres langues car elle tient compte des particularités
            grammaticales de la langue française uniquement.
            C'est aussi l'occasion d'utiliser la surcharge de fonctions,
            disponible depuis Delphi 5 ou 6.
            
 History:
   02/05/2003 publication sur DelphiFr.com
-----------------------------------------------------------------------------}

unit ChiffresEnLettres;

interface
  {La fonction Int2Letters reçoit un nombre sous forme de chaine et renvoie
  son équivalent sous forme littérale.
  Exemple :
  Var
    S : string;
  begin
    S := '1971';
    S := Int2Letters(S);
    ShowMessage(S); //-> mille neuf cent soixante et onze
  end;}
  function Int2Letters(const ANumber: string): string;overload;
  {La fonction Int2Letters reçoit un paramètre sous forme d'entier et renvoie
  son équivalent sous forme littérale. Attention, seuls les entiers de
  4 chiffres maximum seront autorisés.}
  function Int2Letters(const ANumber: integer):string;overload;

implementation

uses
  SysUtils;

const
  Chiffres: array['0'..'9'] of string =
  ('', 'un ', 'deux ', 'trois ', 'quatre ',
    'cinq ', 'six ', 'sept ', 'huit ', 'neuf ');

  LaDizaine: array['0'..'9'] of string =
  ('dix', 'onze', 'douze', 'treize', 'quatorze',
    'quinze', 'seize', 'dix sept', 'dix huit', 'dix neuf');

  Dizaines: array['0'..'9'] of string =
  ('', 'dix ', 'vingt ', 'trente ', 'quarante ',
    'cinquante ', 'soixante ', 'soixante ', 'quatre vingt ',
      'quatre vingt dix ');

function Int2Letters(const ANumber: string): string;
var
  Verif: integer;
  Temp: string;
begin
  Verif := StrToIntDef(ANumber, -1);
  if Verif = -1 then
    Result := Format('%s n''est pas un Chiffres valide', [ANumber])
  else
    case Length(ANumber) of
      4: //Traitement des milliers
        begin
          case ANumber[1] of
            '1': Result := 'mille ';
          else
            Result := Chiffres[ANumber[1]] + 'mille ';
          end;
          Temp := Copy(Anumber, 2, 3);
          Result := Result + Int2Letters(Temp);
        end;
        //Fin Traitement des milliers

      3: //Traitement des centaines
        begin
          case Anumber[1] of
            '0': Result := EmptyStr;
            '1': Result := 'cent ';
          else
            Result := Chiffres[ANumber[1]] + 'cent ';
          end;
          Temp := Copy(ANumber, 2, 2);
          Result := Result + Int2Letters(Temp);
        end;
        //Fin Traitement des centaines

      2: //Traitement des dizaines
        begin
          case ANumber[1] of
            '0':
              begin
                Result := EmptyStr;
                Temp := Copy(Anumber, 2, 1);
                Result := Int2Letters(Temp);
              end;

            '1':
              case ANumber[2] of
                '1'..'6': Result := LaDizaine[ANumber[2]];
              else
                begin
                  Temp := Copy(Anumber, 2, 1);
                  Result := 'dix ' + Int2Letters(Temp);
                end;
              end;

            '2'..'6' :
              case ANumber[2] of
                '0': Result := Dizaines[ANumber[1]];
                '1':
                  begin
                    Result := Dizaines[ANumber[1]] + 'et ';
                    Temp := ANumber[2];
                    Result := Result + Int2Letters(Temp);
                  end;
              else
                begin
                  Result := Dizaines[ANumber[1]];
                  Temp := ANumber[2];
                  Result := Result + Int2Letters(Temp);
                end;
              end;

            '7':
              begin
                case ANumber[2] of
                  '1': Result := Dizaines[ANumber[1]] + 'et ';
                else
                  Result := Dizaines[ANumber[1]];
                end;
                Result := Result + LaDizaine[ANumber[2]];
              end;

            '8':
              begin
                Result := Dizaines[ANumber[1]];
                Temp := ANumber[2];
                Result := Result + Int2Letters(Temp);
              end;

            '9':
              case ANumber[2] of
                '0': Result := Dizaines[ANumber[1]];
              else
                begin
                  Result := Dizaines[pred(ANumber[1])];
                  Result := Result + LaDizaine[ANumber[2]];
                end;
              end;

          end;
        end;
        //Fin Traitement des dizaines
        
      1: //Traitement des unités
          Result := Chiffres[ANumber[1]];

    else
      Result := 'Chiffres trop grand : 4 chiffres maximum autorisés';
    end; {case Length(ANumber)}

end;

function Int2Letters(const ANumber: integer):string;
begin
  Result := Int2Letters(IntToStr(ANumber));
end;

end.

Conclusion :


Compatible D6 et + seulement du fait des directives Overload (surcharge des fonctions).

Codes Sources

A voir également

Ajouter un commentaire Commentaires
cs_ManChesTer Messages postés 374 Date d'inscription vendredi 20 octobre 2000 Statut Modérateur Dernière intervention 15 janvier 2021
7 mai 2003 à 16:36
Merci Japee,

Voici un ptit corrigé (sans les règles grammaticales qui ne sont pas utiles pour etablir un cheque valide).

Function IntToFrench(value:Longint):string;
const Unite : array[0..9] of string=
('Zero','un','deux','trois','quatre','cinq','six','sept','huit','neuf');
Unite2 : array[0..9] of string=
('dix','onze','douze','treize','quatorze','quinze','seize','dix-sept','dix-huit','dix-neuf');
dixaine:array[2..9] of string=
('vingt','trente','quarante','cinquante','soixante','soixante','quatre-vinght','quatre-vingt');
Langage='Francais France';

{const Unite : array[0..9] of string= // pour la belgique
('Zero','un','deux','trois','quatre','cinq','six','sept','huit','neuf');
Unite2 : array[0..9] of string=
('dix','onze','douze','treize','quatorze','quinze','seize','dix-sept','dix-huit','dix-neuf');
dixaine:array[2..9] of string=
('vingt','trente','quarante','cinquante','soixante','septante','quatre-vinght','nonante');
Langage='Francais Belgique';}
var fr : String;
ch : String;
t : String;
begin
fr:='';
ch:=inttostr(value);
while length(ch)>0 do
begin
t:=ch[1];
case length(ch) of
2,5,8:
begin
t:=t+ch[2];
if ((Strtoint(t) in [70..79]) or (Strtoint(t) in [90..99])) and (Langage='Francais France') then
begin
fr:=fr+Dixaine[strtoint(t[1])]+' ';
t:=Inttostr((Strtoint(t)-((strtoint(t[1])*10))+10));
end;
if strtoint(t)<20 then
begin
fr:=fr+unite2[strtoint(t)-10]+' ';
delete(ch,1,1);
end
else
fr:=fr+Dixaine[strtoint(t[1])]+' ';
end;
1,3,4,6,7,9,10:
if not ((length(ch) in [3,6,9]) and(t[1]='1')) then
begin
if length(ch)=1 then
fr:=fr+unite[strtoint(t)]
else
fr:=fr+unite[strtoint(t)]+' ';
end;
end;
delete(ch,1,1);
if length(ch)=0 then break;
case length(ch) of
9 :fr:=fr+'milliard ';
6 :fr:=fr+'million ';
3 :fr:=fr+'mille ';
2,5,8 :fr:=fr+'cent ';
end;
if (strtoint(ch)=0) then
begin
case length(ch) of
4,5 :Fr:=Fr+'mille';
7,8 :Fr:=Fr+'Million';
10 :Fr:=Fr+'Milliard';
end;
break;
end;
end;
fr:=trim(fr);
fr[1]:=uppercase(fr[1])[1];
result:=fr;
end;

Bon coding ....

ManChesTer.
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
6 mai 2003 à 16:04
Tout bien reçu 5 sur 5, Delphiprog.

J'espère néanmoins que je n'ai pas eu l'air de dire "bah, tu vois, c'est trop facile, t'as qu'a rajouter ça et ça marche impec". J'en serais désolé :-{
J'ai fait ce truc plutôt genre "tiens, je fais le point sur ce que je sais faire avec les routines de gestion de chaîne", sans trop savoir au départ si j'arriverais quelque part... d'où un espèce de débordement enthousiaste.

Amitiés Delphistes :-D
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
6 mai 2003 à 14:30
Merci pour cette intéressante proposition.
Mais plutôt que l'enrobage (l'encapsulation a un autre sens), il serait mieux de l'intéger et de déclarer ta fonction à l'intérieur de la fonction Int2Letters, et de n'y faire appel que dans les cas nécessaires.
Mais on peut utiliser d'autres techniques encore plus performantes. Non pas que la tienne ne le soit pas, mais les comparaisons de chaînes de caractères sont toujours consommatrices de temps de traitement.

Rendez-vous dans quelques temps pour une copie corrigée et complétée...

Merci à tous les trois pour vos remarques constructives.
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
6 mai 2003 à 11:17
Merci à toi Delphiprog, pour ce beau bout de code !
Je l'ai tout récemment installé, sous D4, sans trop y croire, ben ça marche du tonnerre de Brest...
Me reste plus qu'à essayer de tout comprendre ;-)

Voilà, je vais passer pour un forcené, mais ça me démangeait :
En réponse à l'inquiétude bien légitime de Nono40 quant au respect strict de certaines règles grammaticales concernant l'accord au pluriel de "vingt" et de "cent", j'ai pondu une petite fonction qui prend ça en charge. J'en ris encore :-)))))

function Ortho(A_Verifier: String): String;
begin
if Pos('quatre vingt', A_Verifier) <> 0 then
begin
if Length(A_Verifier) - Pos('quatre vingt', A_Verifier) = 12 then
Insert('s', A_Verifier, Pos('quatre vingt', A_Verifier) + 12);
end else
if Pos('cent', A_Verifier) > 1 then
begin
if Length(A_Verifier) - Pos('cent', A_Verifier) = 4 then
Insert('s', A_Verifier, Pos('cent', A_Verifier) + 4);
end;
Result := A_Verifier;
end;

Ca fonctionne très bien avec ta fonction, Delphiprog. Il suffit de l'encapsuler ainsi :
Ortho(Int2Letters(LeNombre));
Il faut éventuellement l'adapter pour qu'elle fonctionne avec un autre programme similaire, mais le principe me semble cohérent...

Bonne Prog !
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
5 mai 2003 à 20:40
Merci pour ces précisions Japee.
Si je n'ai pas fait les accords que nous a indiqués Nono40, en revanche les particularités de la langue française que tu mentionnes sont bien prises en compte. C'est surement ce qui explique un code un peu plus long.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.