解决方案 »

  1.   

    unit calculator;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type TStack=class
         private
           StackData:array[1..100] of string;
         public
           IsEmpty:boolean;
           TopPointer:integer;
           procedure Init;
           function Find(var data:string;i:integer):boolean;
           function Pop(var data:string):boolean;
           function Push(data:string):boolean;
    end;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Edit2: TEdit;
        Label1: TLabel;
        Label2: TLabel;
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        procedure StoreExpression(input:string);
        function TransformExpression:boolean;
        function Calculate(var Aresult:real):boolean;
      end;var
      Form1: TForm1;
      ExpressionStack,tempStack,NiPolandStack:TStack;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
      ExpressionStack:=TStack.Create;
      tempStack:=TStack.Create;
      NiPolandStack:=TStack.Create;
      ExpressionStack.Init;
      tempStack.Init;
      NiPolandStack.Init;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      jg:real;
      input:string;
    begin
      ExpressionStack.Init;
      tempStack.Init;
      NiPolandStack.Init;
      input:=edit1.Text;
      StoreExpression(input);
      if TransformExpression then
      begin
       if Calculate(jg) then edit2.Text:=floattostr(jg)
       else edit2.Text:='Syntax Error';
      end
      else edit2.Text:='Syntax Error';
    end;function TStack.Find(var data:string;i:integer):boolean;
    begin
      if (i>TopPointer) or (i<1) then begin
         result:=false;
         exit;
      end;  data:=StackData[i];
      result:=true;
    end;procedure TStack.Init;
    begin
      TopPointer:=0;
      IsEmpty:=True;
    end;function TStack.Pop(var data: string): boolean;
    var aData:string;
    begin
      if not Find(aData,TopPointer) then begin
         result:=false;
         exit;
      end;
      data:=aData;
      stackData[TopPointer]:='';
      dec(TopPointer);
      if TopPointer<=0 then IsEmpty:=true else IsEmpty:=false;
      result:=true;end;function TStack.Push(data: string): boolean;
    begin
      if TopPointer>=100 then begin
         result:=false;
         exit;
      end;
      isEmpty:=false;
      inc(TopPointer);
      StackData[TopPointer]:=data;
      result:=true;
    end;
    procedure TForm1.StoreExpression(input:string);
    var temp:char;
        temp1:string;
        i:integer;
        v:string;
    begin  v:='';
      for i:=1 to length(input) do begin
          temp:=input[i];
          if temp in ['+','-','*','/','(',')'] then begin
             if v<>'' then ExpressionStack.Push(v);
             ExpressionStack.Find(temp1,ExpressionStack.TopPointer);
             if (temp='-') and ((temp1='(') or (ExpressionStack.IsEmpty))then ExpressionStack.Push('0');
             ExpressionStack.Push(temp);
             v:='';
          end else begin
            v:=v+temp;
          end;
      end;
      if v<>'' then ExpressionStack.Push(v);
    end;function TForm1.TransformExpression:boolean;
    var i:integer;
        str:string;
        temp:string;
        value,code:integer;
    begin
      result:=true;
      for i:=1 to ExpressionStack.TopPointer do begin
          ExpressionStack.Find(str,i);
          val(str,value,code);
          if code=0 then NiPolandStack.Push(str)
          else begin
            if str[1] in ['+','-','*','/','0','1','2','3','4','5','6','7','8','9','(',')'] then
            begin
             if (str='+') or (str='-') then begin
                while not tempStack.IsEmpty do begin
                   tempStack.Find(temp,tempStack.TopPointer);
                   if temp='(' then break;
                   tempStack.Pop(temp);
                   NiPolandStack.Push(temp);
                end;
             end;
             if (str='*') or (str='/') then begin
                while not tempStack.IsEmpty do begin
                   tempStack.Find(temp,tempStack.TopPointer);
                   if (temp='(') or (temp='-') or (temp='+') then break;
                   tempStack.Pop(temp);
                   NiPolandStack.Push(temp);
                end;
             end;
             if str=')' then begin
                result:=false;
                while not tempStack.IsEmpty do begin
                   tempStack.Find(temp,tempStack.TopPointer);
                   if (temp='(') then begin
                       result:=true;
                       tempStack.Pop(temp);
                       break;
                   end;
                   tempStack.Pop(temp);
                   NiPolandStack.Push(temp);
                end;
             end;
             if str<>')' then tempStack.Push(str);
            end
            else 
             result:=false;
          end;
      end;  while not tempStack.IsEmpty do begin
         tempStack.Pop(temp);
         NiPolandStack.Push(temp);
      end;
      NiPolandStack.Find(temp,1);
    end;function TForm1.Calculate(var Aresult:real):boolean;
    var i:integer;
        temp:string;
        stra,strb:string;
        inta,intb,tempResult:real;
        code:integer;
    begin
      Result:=false;
      ExpressionStack.Init;
      tempStack.Init;
      tempResult:=0;  for i:=1 to NiPolandStack.TopPointer do begin
          NiPolandStack.find(temp,i);
          case temp[1] of
           '+','-','*','/':begin
                 if not tempStack.Pop(stra) then exit;
                 if not tempStack.Pop(strb) then exit;
                 val(stra,inta,code);
                 if code<>0 then exit;
                 val(strb,intb,code);
                 if code<>0 then exit;
                 if temp='+' then tempResult:=intb+inta;
                 if temp='-' then tempResult:=intb-inta;
                 if temp='*' then tempResult:=intb*inta;
                 if temp='/' then begin
                    if inta=0 then exit;
                    tempResult:=intb/inta;
                 end;
                 tempStack.Push(floattostr(tempResult));
           end;
           else tempStack.Push(temp);
          end;
      end;
      tempStack.Pop(temp);
      if not tempStack.IsEmpty then exit;
      Aresult:=tempResult;
      result:=true;
    end;
    end.