Accueil > > > CALCULER UNE OPERATION PRESENTE DANS UNE STRING (GESTION DES NOMBRES A VIRGULES)
CALCULER UNE OPERATION PRESENTE DANS UNE STRING (GESTION DES NOMBRES A VIRGULES)
Information sur la source
Description
Ce code permet de calculer une operation basique presentent dans une chaine de caractere, comme par exemple (3*5(10-2))/10 (qui renvoi 12) Cependant il ne prend pas en compte les priorité de multiplications et de division, et donc 5+3*2 revien pour lui à 8*2 (pour lui faire comprendre faut faire 5+(3*2)) il gere aussi les float (type single), donc 3*3.33333333333 = 10 ou preske :P je mets pas de zip, il suffit de faire un copier coller dans un fichier
Source
- (*--------------------------------------------//
- Calculatrice de chaines (resultat a virgule)
- Par anK (legere modif. de Bestiol :))
- Bug(s): lorsqu'on divise par 0... :D
- //--------------------------------------------*)
-
-
- unit Unit1;
-
- interface
-
- uses strUtils,sysUtils;
-
- type
- TOperation=(loAdd,loSub,loMul,loDiv);
-
- function CalculStr(Str:String):Single;
-
- const
- Niveau_Parentheses=15;
-
- implementation
-
- function SimplifyStr(Str:string):string;
- const
- Smpl: Array[0..3]Of String = ('++', '--', '+-', '-+'); //: Tableau des doublons à simplifier
- SmplPar: Array[0..3]Of String = ('+' , '+' , '-' , '-');//: Par quoi il faut les remplacer
-
- var i: Integer;
-
- begin
- //ça bug encore si il y a --- ou +++ ect... mais a part ça c nikel ;)
- //Plus maintenant ! ;o)
- Result := Str;
-
- for i := Low(Smpl) to High(Smpl) do
- While Pos(Smpl[i], Result) > 0 do
- Result := AnsiReplaceStr(Result, Smpl[i], SmplPar[i]);
-
- Result := AnsiReplaceStr(Result, '*(', '(');
- Result := AnsiReplaceStr(Result, '()','');
- Result := AnsiReplaceStr(Result, ' ',''); //On comble les trous!
- Result := AnsiReplaceStr(Result, '.',','); //Les . sont transformés en ,
- end;
-
- function CalculStr(Str:String):Single;
- var
- I,J:integer;
- LastOperande: TOperation;
- zPar: array[0..Niveau_Parentheses] of single; //Profondeur des parentheses
- tPar: array[1..Niveau_Parentheses] of TOperation; //Type liason entre la parenthese et sa superieure
- PeC: 0..Niveau_Parentheses; //Parenthese en Cours
- fstOp: boolean; //Premier operateur
- ActuNombre: boolean; //Si actuellement il y a un nombre...
- TailleNombre: Word;
- DebutNombre: Word;
- StringTemp: string;
- DejaVirgule: boolean; //Si le nombre a deja une virgule...
-
- procedure CalculUneOperation;
- var Nombre:single;
- begin
- Nombre:=StrtoFloat(Copy(StringTemp,DebutNombre,TailleNombre));
- case LastOperande of
- loAdd:
- zPar[PeC]:=zPar[PeC]+Nombre;
- loSub:
- zPar[PeC]:=zPar[PeC]-Nombre;
- loMul:
- zPar[PeC]:=zPar[PeC]*Nombre;
- loDiv:
- zPar[PeC]:=zPar[PeC]/Nombre;
- end;
- end;
-
- procedure StopNombre;
- begin
- DejaVirgule := False;
- ActuNombre := False;
- end;
-
- procedure InitParenthese;
- begin
-
- end;
-
- const
- Nombre = ['0'..'9']; //On a dans nombre aussi le '.', mais il est comptabilisé differement :)
- Signe = ['+','-','*','/'];
- Parenthese = ['(',')'];
- begin
- //-------------Initialisation-----------------
- LastOperande := loAdd;
- fstOp := True;
- PeC := 0;
- zPar[0] := 0;
- ActuNombre := False;
- DejaVirgule := False;
- //--------------------------------------------
- StringTemp := SimplifyStr(Str); //Simplification des calculs (++ devient + ect...)
- for I:=1 to Length(Str) do //Debut de la boucle
- begin
-
- //-------------Les Nombres -------------------
- if StringTemp[I] in Nombre then
- begin
- if not ActuNombre then //Si un nombre n'est pas deja "Lancé"
- begin
- //On le "lance"
- ActuNombre := True;
- DebutNombre := I;
- fstOp:=False;
- end;
- end;
- //--------------------------------------------
-
- //-------------La virgule --------------------
- if StringTemp[I] = ',' then
- begin
- if (not DejaVirgule) and ActuNombre then
- begin
- //On rajoute la virgule au nombre deja lancé
- DejaVirgule:=True; // =)
- end else begin
- //ERREUR dans la string meme...
- end;
- end;
- //--------------------------------------------
-
- //---------Parentheses ouvertes---------------
-
- if StringTemp[I] = '(' then
- begin
- if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
- begin
- TailleNombre := I-DebutNombre;
- ActuNombre := False;
- CalculUneOperation; //On calcul la derniere operation
- inc(PeC);
- zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
- //Donc si il y a un nombre k(x) on a k*x
- tPar[PeC] := loMul;
- //zPar[PeC] := 0;
- //Comme dans toute parenthese, le FirstOperateur=true, et on commence par un add
- LastOperande := loAdd;
- fstOp := True;
- end else
- begin
- inc(PeC);
- zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
- tPar[PeC] := LastOperande;//Le dernier operateur avant la parenthese
- LastOperande := loAdd;
- fstOp := True;
- end;
- end;
-
- //---------Parentheses fermé---------------
-
-
- if StringTemp[I] = ')' then
- begin
- //On s'assure la finalisation du dernier nombre de la parenthese
- if ActuNombre then
- begin
- TailleNombre:=I-DebutNombre;
- CalculUneOperation; //On finalise si jamais il resté un nombre...
- end;
-
- case tPar[PeC] of //On mets à jour la parenthese inferieur
- loMul:zPar[PeC-1]:=zPar[Pec-1]*zPar[Pec];
- loAdd:zPar[PeC-1]:=zPar[Pec-1]+zPar[Pec];
- loSub:zPar[PeC-1]:=zPar[Pec-1]-zPar[Pec];
- loDiv:zPar[PeC-1]:=zPar[Pec-1]/zPar[Pec];
- end;
- if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
- begin
- TailleNombre:=I-DebutNombre;
- ActuNombre:=False;
- CalculUneOperation; //On calcul la derniere operation
- //Donc si il ya un nombre k(x) on a k*x
- //LastOperande:=loMul; //Donc on multiplie ;)
- end;
- dec(PeC);
- end;
-
-
- //--------------------------------------------
-
-
- //-------------Le signe Plus-----------------
-
- if StringTemp[I] = '+' then
- begin
-
- if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
- begin
- //C'est le premier operateur, donc un debut de nombre...
- if StringTemp[I+1] in Nombre then //On debute un nombre...
- begin
- fstOp := False;
- ActuNombre := True;
- DebutNombre := (I+1);//Sans prendre en compte le +
- end;
- end;
-
- if ActuNombre then //Si un nombre est déja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loAdd; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loSub; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------Le signe Moins-----------------
-
- if StringTemp[I] = '-' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loSub; //On change ce dernier operateur :)
- end;
-
- if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
- begin
- //C'est le premier operateur, donc un debut de nombre...
- if StringTemp[I+1] in Nombre then //On debute un nombre...
- begin
- fstOp := False;
- ActuNombre := True;
- DebutNombre := I;
- end;
- end;
-
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loSub; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------Le signe Multiplication--------
-
- if StringTemp[I] = '*' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loMul; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loMul; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------La Division--------------------
-
- if StringTemp[I] = '/' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loDiv; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loDiv; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- end;
-
- if ActuNombre then
- begin
- TailleNombre:=Length(StringTemp)-I;
- CalculUneOperation; //On finalise si jamais il resté un nombre...
- end;
- Result:=zPar[0]; //On fou dans result le nombre trouvé...
- end;
-
- end.
(*--------------------------------------------//
Calculatrice de chaines (resultat a virgule)
Par anK (legere modif. de Bestiol :))
Bug(s): lorsqu'on divise par 0... :D
//--------------------------------------------*)
unit Unit1;
interface
uses strUtils,sysUtils;
type
TOperation=(loAdd,loSub,loMul,loDiv);
function CalculStr(Str:String):Single;
const
Niveau_Parentheses=15;
implementation
function SimplifyStr(Str:string):string;
const
Smpl: Array[0..3]Of String = ('++', '--', '+-', '-+'); //: Tableau des doublons à simplifier
SmplPar: Array[0..3]Of String = ('+' , '+' , '-' , '-');//: Par quoi il faut les remplacer
var i: Integer;
begin
//ça bug encore si il y a --- ou +++ ect... mais a part ça c nikel ;)
//Plus maintenant ! ;o)
Result := Str;
for i := Low(Smpl) to High(Smpl) do
While Pos(Smpl[i], Result) > 0 do
Result := AnsiReplaceStr(Result, Smpl[i], SmplPar[i]);
Result := AnsiReplaceStr(Result, '*(', '(');
Result := AnsiReplaceStr(Result, '()','');
Result := AnsiReplaceStr(Result, ' ',''); //On comble les trous!
Result := AnsiReplaceStr(Result, '.',','); //Les . sont transformés en ,
end;
function CalculStr(Str:String):Single;
var
I,J:integer;
LastOperande: TOperation;
zPar: array[0..Niveau_Parentheses] of single; //Profondeur des parentheses
tPar: array[1..Niveau_Parentheses] of TOperation; //Type liason entre la parenthese et sa superieure
PeC: 0..Niveau_Parentheses; //Parenthese en Cours
fstOp: boolean; //Premier operateur
ActuNombre: boolean; //Si actuellement il y a un nombre...
TailleNombre: Word;
DebutNombre: Word;
StringTemp: string;
DejaVirgule: boolean; //Si le nombre a deja une virgule...
procedure CalculUneOperation;
var Nombre:single;
begin
Nombre:=StrtoFloat(Copy(StringTemp,DebutNombre,TailleNombre));
case LastOperande of
loAdd:
zPar[PeC]:=zPar[PeC]+Nombre;
loSub:
zPar[PeC]:=zPar[PeC]-Nombre;
loMul:
zPar[PeC]:=zPar[PeC]*Nombre;
loDiv:
zPar[PeC]:=zPar[PeC]/Nombre;
end;
end;
procedure StopNombre;
begin
DejaVirgule := False;
ActuNombre := False;
end;
procedure InitParenthese;
begin
end;
const
Nombre = ['0'..'9']; //On a dans nombre aussi le '.', mais il est comptabilisé differement :)
Signe = ['+','-','*','/'];
Parenthese = ['(',')'];
begin
//-------------Initialisation-----------------
LastOperande := loAdd;
fstOp := True;
PeC := 0;
zPar[0] := 0;
ActuNombre := False;
DejaVirgule := False;
//--------------------------------------------
StringTemp := SimplifyStr(Str); //Simplification des calculs (++ devient + ect...)
for I:=1 to Length(Str) do //Debut de la boucle
begin
//-------------Les Nombres -------------------
if StringTemp[I] in Nombre then
begin
if not ActuNombre then //Si un nombre n'est pas deja "Lancé"
begin
//On le "lance"
ActuNombre := True;
DebutNombre := I;
fstOp:=False;
end;
end;
//--------------------------------------------
//-------------La virgule --------------------
if StringTemp[I] = ',' then
begin
if (not DejaVirgule) and ActuNombre then
begin
//On rajoute la virgule au nombre deja lancé
DejaVirgule:=True; // =)
end else begin
//ERREUR dans la string meme...
end;
end;
//--------------------------------------------
//---------Parentheses ouvertes---------------
if StringTemp[I] = '(' then
begin
if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
begin
TailleNombre := I-DebutNombre;
ActuNombre := False;
CalculUneOperation; //On calcul la derniere operation
inc(PeC);
zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
//Donc si il y a un nombre k(x) on a k*x
tPar[PeC] := loMul;
//zPar[PeC] := 0;
//Comme dans toute parenthese, le FirstOperateur=true, et on commence par un add
LastOperande := loAdd;
fstOp := True;
end else
begin
inc(PeC);
zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
tPar[PeC] := LastOperande;//Le dernier operateur avant la parenthese
LastOperande := loAdd;
fstOp := True;
end;
end;
//---------Parentheses fermé---------------
if StringTemp[I] = ')' then
begin
//On s'assure la finalisation du dernier nombre de la parenthese
if ActuNombre then
begin
TailleNombre:=I-DebutNombre;
CalculUneOperation; //On finalise si jamais il resté un nombre...
end;
case tPar[PeC] of //On mets à jour la parenthese inferieur
loMul:zPar[PeC-1]:=zPar[Pec-1]*zPar[Pec];
loAdd:zPar[PeC-1]:=zPar[Pec-1]+zPar[Pec];
loSub:zPar[PeC-1]:=zPar[Pec-1]-zPar[Pec];
loDiv:zPar[PeC-1]:=zPar[Pec-1]/zPar[Pec];
end;
if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
begin
TailleNombre:=I-DebutNombre;
ActuNombre:=False;
CalculUneOperation; //On calcul la derniere operation
//Donc si il ya un nombre k(x) on a k*x
//LastOperande:=loMul; //Donc on multiplie ;)
end;
dec(PeC);
end;
//--------------------------------------------
//-------------Le signe Plus-----------------
if StringTemp[I] = '+' then
begin
if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
begin
//C'est le premier operateur, donc un debut de nombre...
if StringTemp[I+1] in Nombre then //On debute un nombre...
begin
fstOp := False;
ActuNombre := True;
DebutNombre := (I+1);//Sans prendre en compte le +
end;
end;
if ActuNombre then //Si un nombre est déja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loAdd; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loSub; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------Le signe Moins-----------------
if StringTemp[I] = '-' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loSub; //On change ce dernier operateur :)
end;
if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
begin
//C'est le premier operateur, donc un debut de nombre...
if StringTemp[I+1] in Nombre then //On debute un nombre...
begin
fstOp := False;
ActuNombre := True;
DebutNombre := I;
end;
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loSub; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------Le signe Multiplication--------
if StringTemp[I] = '*' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loMul; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loMul; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------La Division--------------------
if StringTemp[I] = '/' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loDiv; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loDiv; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
end;
if ActuNombre then
begin
TailleNombre:=Length(StringTemp)-I;
CalculUneOperation; //On finalise si jamais il resté un nombre...
end;
Result:=zPar[0]; //On fou dans result le nombre trouvé...
end;
end.
Conclusion
exemple d'utilisation: ShowMessage(Floattostr(CalculStr('8/10')));
Si jamais des bugs apparaissent (et il doit y en avoir) merci de me le dire :)
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
TECHDAYS PARIS 2012 : COMMENT SHAREPOINT A SAUVé MES TECHDAYSTECHDAYS PARIS 2012 : COMMENT SHAREPOINT A SAUVé MES TECHDAYS par ROMELARD Fabrice
Speakers : Lionel Limozin et Alain Marty La session commence par une découverte de SharePoint à travers la mise en place d'un environnement SharePoint pour la gestion des Sessions animées par BeWise. Le besoin est très ba...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice PERSPECTIVE 3.0 POUR SILVERLIGHT 5.0PERSPECTIVE 3.0 POUR SILVERLIGHT 5.0 par odewit
Je viens de publier la version 3.0 de Perspective pour Silverlight, qui regroupe un portage sous Silverlight 5.0 des fonctionnalités de Perspective 2.0, le framework 3D de haut-niveau introduit récemment et de nouveaux exemples de code. En voici la li...
Cliquez pour lire la suite de l'article par odewit TECHDAYS PARIS 2012 : TOP 10 DES BEST PRACTICES POUR SQL SERVERTECHDAYS PARIS 2012 : TOP 10 DES BEST PRACTICES POUR SQL SERVER par ROMELARD Fabrice
Speaker : Nadia Ben El Kadi Configuration machine La session commence par la toute première question à se poser lors de la mise en place d'environnement SQL Server, la configuration des machines : Type de mac...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2012 : KINECT + OFFICE 365 UN BON GESTE POUR VOTRE SITECHDAYS PARIS 2012 : KINECT + OFFICE 365 UN BON GESTE POUR VOTRE SI par ROMELARD Fabrice
Speakers : Fabrice Barbin, Samuel Blanchard, Julien Lo Presti Titre Prometteur et attractif invitant à voir comment lier le composant ludique Kinect dans le cadre d'une structure IT classique, notamment au travers de la plat...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2012 : PLEINIèRE DU PREMIER JOURTECHDAYS PARIS 2012 : PLEINIèRE DU PREMIER JOUR par ROMELARD Fabrice
KeyNotes du premier jour pour les développeurs. La session est principalement axée sur une des principales directions prise par Microsoft à travers tous ses nouveaux produits : Cloud privé ou public (Solution Azure) ...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|