Newsgroup: it.comp.lang.delphi
Titolo: Calcolare l'espressione contenuta in una Stringa?

Ciao,
Come da subject ho un'espressione contenuta in una stirnga per esempio :
var
    expr:String;
    myRES:integer;
begin
    expr := '(10/2)*100';
    Come faccio a calcolare il valore di expr ???
    myRES := ???????;
end;
grazie a tutti
ciao!!

    Come faccio a calcolare il valore di expr ???
Devi scrivere un parser.
Non e` semplicissimo ma si puo` fare, la via piu` semplice e`
implementare un parser a discesa ricorsiva.  Cerca in rete qualche
riferimento.  Probabilmente trovi dei componenti gia` pronti.
 


Ti posto il codice, ti servono due edit (Edit1 ed Edit2) e un bottone
chiamato "Calcola".
Al click di calcola assegna l'apposita procedura.
Prova e fammi sapere.
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
  StdCtrls;
type
  TFormCalcola = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Calcola: TButton;
    procedure CalcolaClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  FormCalcola: TFormCalcola;
implementation
{$R *.DFM}
const tkNULL   = #00;
      tkNUMBER = #01;
      tkPLUS   = '+';
      tkMINUS  = '-';
      tkMUL    = '*';
      tkDIV    = '/';
      tkLP     = '(';
      tkRP     = ')';
var
  CurrentToken: Char;
  NumberValue: Double;
  ExprStr: String;
procedure GenerateError(Msg: String);
begin
  raise Exception.Create(Msg);
end;
function Expression(GetFlag: Boolean): Double; forward;
procedure GetToken;
var
  NumStr: String;
begin
  if (ExprStr = '') then
    CurrentToken := tkNULL
  else
  if (ExprStr[1] in ['0'..'9']) then
  begin
    NumStr := '';
    while ((ExprStr <> '') and
           (ExprStr[1] in ['0'..'9'])) do
    begin
      NumStr := NumStr + ExprStr[1];
      Delete(ExprStr, 1, 1);
    end;
    NumberValue := StrToFloat(NumStr);
    CurrentToken := tkNUMBER;
  end
  else
  if (ExprStr[1] in ['+', '-', '*', '/', '(', ')']) then
  begin
    case ExprStr[1] of
       '+' : CurrentToken := tkPLUS;
       '-' : CurrentToken := tkMINUS;
       '*' : CurrentToken := tkMUL;
       '/' : CurrentToken := tkDIV;
       '(' : CurrentToken := tkLP;
       ')' : CurrentToken := tkRP;
    end;
    Delete(ExprStr, 1, 1);
  end
  else
    CurrentToken := tkNULL;
end;
function Prim(GetFlag: Boolean): Double;
var
  V: Double;
begin
  if (GetFlag) then GetToken;
  case CurrentToken of
    tkNUMBER : begin
                 V := NumberValue;
                 GetToken;
                 Result := V;
                 Exit;
               end;
    tkMINUS  : begin
                 Result := -Prim(True);
               end;
    tkLP     : begin
                 V := Expression(True);
                 if (CurrentToken <> tkRP) then
                   GenerateError('Errore: attesa )');
                 GetToken;
                 Result := V;
                 Exit;
               end;
  else
    GenerateError('Errore di sintassi!');
  end
end;
function Term(GetFlag: Boolean): Double;
var
  D, Left: Double;
begin
  Left := Prim(GetFlag);
  while (True) do
  begin
    case CurrentToken of
      tkMUL : Left := Left * Prim(True);
      tkDIV : begin
                D := Prim(True);
                if (D = 0) then
                  GenerateError('Divisione per zero!');
                Left := Left / D;
              end;
    else
      begin
        Result := Left;
        Exit
      end
    end
  end
end;
function Expression(GetFlag: Boolean): Double;
var
  Left: Double;
begin
  Left := Term(GetFlag);
  while (True) do
  begin
    case (CurrentToken) of
      tkPLUS  : Left := Left + Term(True);
      tkMINUS : Left := Left - Term(True);
    else
      begin
        Result := Left;
        Exit;
      end
    end
  end
end;
function NoSpaces(S: String): String;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to Length(S) do
  begin
    if S[I] <> ' ' then
    begin
      Result := Result + S[I];
    end;
  end;
end;
procedure TFormCalcola.CalcolaClick(Sender: TObject);
begin
  ExprStr := NoSpaces(Edit1.Text);
  Edit2.Text := FloatToStr(Expression(True));
end;
end.

Prova e fammi sapere.
Fai sapere qualcosa anche a me, considerato che quel codice l'ho
scritto io ;)

 scritto io ;)
Infatti io mi ero salvato il tuo messaggio, e vedendo quello di Karletto ho
pensato : Eppure questo l'ho già visto !!
Karletto, Karletto almeno cita le fonti !!
Ciao

 scritto io ;)
Ciao,
Rieccomi  :-) ho modificato un pochino il codice alle mie esigenze perchč
non gestiva i decimali, lo riposto qui sotto,
cmq grazie a tutti per avermi fatto risparmiare un bel po di tempo :-)
NB: non gestisco gli errori e li facci tonrare a 0 per una mia particolare
esigenza :-)
ciao e grazie
Alberto
unit parser;
interface
uses
  SysUtils, Classes;
type
  TFormCalcola = class(TObject)
    function Calcola(expr:String):String;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  ParserExpr: TFormCalcola;
implementation
const tkNULL   = #00;
      tkNUMBER = #01;
      tkPLUS   = '+';
      tkMINUS  = '-';
      tkMUL    = '*';
      tkDIV    = '/';
      tkLP     = '(';
      tkRP     = ')';
var
  CurrentToken: Char;
  NumberValue: Double;
  ExprStr: String;
function Expression(GetFlag: Boolean): Double; forward;
procedure GetToken;
var
  NumStr: String;
begin
  if (ExprStr = '') then
    CurrentToken := tkNULL
  else
  if (ExprStr[1] in ['0'..'9',',']) then
  begin
    NumStr := '';
    while ((ExprStr <> '') and
           (ExprStr[1] in ['0'..'9',','])) do



                   result := 0;
                 GetToken;
                 Result := V;
                 Exit;
               end;
  else
    result := 0;
  end
end;
function Term(GetFlag: Boolean): Double;
var
  D, Left: Double;
begin
  Left := Prim(GetFlag);
  while (True) do
  begin
    case CurrentToken of
      tkMUL : Left := Left * Prim(True);
      tkDIV : begin
                D := Prim(True);
                if (D = 0) then
                  result := 0;



function TFormCalcola.Calcola(expr:String):String;
begin
  ExprStr := NoSpaces(expr);
  result  := FloatToStr(Expression(True));
end;
end.


Kiedo venia...
Io non ho detto di aver scritto quel codice, almeno non mi risulta...
Non mi ricordavo dove l'avevo preso (sicuramente l'avrò copiato a te) per
questo non ho citato l'autore...
Sono perdonato?
Non volevo di certo spacciare roba mia per tua, solo che ricordavo di avere
quel codice ed essendo ciò che serviva ad alberto, gliel'ho postato.
Ciao