Soit une chaîne de caractères du type "s:='5+3+4+7';";faisons
le programme qui évalue cette chaîne de caractères.
Voyons l'algorithme de cette procédure :
- d'abord on sait que la valeur d'une chaîne vide est 0
- ensuite on sait évaluer un nombre seul avec la fonction
"strToInt".
- on sait extraire une sous-chaîne avec la fonction "copy" et
nous allons extraire des caractères jusqu'au premier signe "+"
- l'évaluation de la chaîne initiale est égale à la valeur du nombre
extrait plus la valeur de la chaîne restante (appel récursif).
Voici le programme correspondant :
function eval(st: string): integer;
var a, i: integer;
begin
if length(st) = 0 then
eval := 0
else
begin
i := 1;
repeat inc(i)until (i > length(st)) or (st[i] = '+');
a := strToInt(copy(st, 1, i - 1));
delete(st, 1, i - 1);
eval := a + eval(st)
end;
end;
On appelle cette fonction de la façon suivante :
b:=eval('+51+7+67+31');
Soit une chaîne de caractères du type
"s:='5+3*4/2-5*3+4*7/2';";faisons le programme qui évalue cette
chaîne de caractères.
La première chose à faire est la séparation des termes; on doit en effet
extraire tous les termes qui sont séparés par des "+" et des
"-".
Ensuite nous devons évaluer chacun des termes extraits, pour arriver à
la fin à une somme (ou à une différence) de termes.
Pour commencer, on suppose qu'on doit évaluer une somme (ou une
différence) de termes. Pour cela, nous reprenons le programme fait
précédemment, et nous l'enrichissons, de façon à ce qu'il puisse évaluer aussi
les différences.
function eval(st: string): integer;
var a, i: integer;
begin
if length(st) = 0 then
eval := 0
else
begin
i := 1;
repeat inc(i)until (i > length(st)) or (st[i] in ['+', '-']);
a := strToInt(copy(st, 1, i - 1));
delete(st, 1, i - 1);
eval := a + eval(st)
end;
end;
Maintenant, on doit créer la procédure qui évalue une expression formée uniquement de produits et quotients; ici, on ne peut pas appliquer la même méthode : pour les sommes, on évaluait le premier terme auquel on ajoutait le résultat du reste.
Mais avec les produits et les quotients, c'est différent : en effet, si on veut évaluer le résultat de "12/4*6/2" on ne peut pas dire qu’il est égal à la valeur du premier terme "12" divisé par la valeur du reste "4*6/2". Le résultat est en réalité "((12/4)*6)/2" soit 9.
Il faut donc lire non pas de gauche à droite, mais de droite à gauche.
Ainsi le résultat de "12/4*6/2" est égal au résultat de "12/4*6" divisé par 2.
Le résultat de "12/4*6" est égal au résultat de "12/4" multiplié par 6
Le résultat de "12/4" est égal au résultat de "12" divisé par 4.
On peut évaluer cette expression, soit 3.
On a, en remontant dans les appels récursifs, 3*6=18.
On a, en remontant encore une fois dans les appels récursifs, 18/2=9.
L'algorithme est le suivant :
- on lit une expression de la droite vers la gauche.
- si on est sur un signe "*" alors :
- on extrait le dernier nombre de la chaîne
- on évalue la chaîne restante
- le résultat est égal à l'évaluation de la chaîne restante (appel récursif) multipliée par le dernier nombre
- si on est sur un signe "/" alors :
- on extrait le dernier nombre de la chaîne
- on évalue la chaîne restante
- le résultat est égal à l'évaluation de la chaîne restante (appel récursif) divisée par le dernier nombre
- si on est au début de la chaîne (aucune multiplication, ni division)
alors :
- le résultat est égal à
l'évaluation du nombre.
Voici le programme qui évalue une expression mathématique contenant des
nombres entiers et les 4 opérations mathématiques. Ce programme fonctionne avec
des nombres entiers. Ainsi, quand vous faites une division, si elle ne tombe
pas juste, le résultat est arrondi, grâce à la fonction "div". Mais
la transformation en réels est très facile.
function eval0(st: string): integer;
var a, i: integer;
signe: char;
begin
i := length(st);
repeat dec(i)until (i = 0) or (st[i] in ['*', '/']);
a := strToInt(copy(st, i + 1, length(st) - i));
if i > 0 then signe := st[i] else signe := #0;
delete(st, i, length(st) - 1 + i);
if signe = '*' then eval0 := eval0(st) * a else
if signe = '/' then eval0 := eval0(st) div a else
eval0 := a;
end;
function eval(st: string): integer;
var a, i: integer;
begin
if length(st) = 0 then
eval := 0
else
begin
i := 1;
repeat inc(i)until (i > length(st)) or (st[i] in ['+', '-']);
a := eval0(copy(st, 1, i - 1));
delete(st, 1, i - 1);
eval := a + eval(st)
end;
end;
Télécharger le code source Delphi