有这样的一个问题:
    如何计算四则运算,如用户输入125+12*(123)/12, 计算其值.     

解决方案 »

  1.   

    计算一个加减乘除表达式的例子:unit compute;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Math;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        Edit2: TEdit;
        procedure Button1Click(Sender: TObject);  private
        { Private declarations }
        s: string;
        function GetNumber(): real;
        function comp(a, b: char): char;
        function cal(a, b: real; p: char): real;
        function expr(): real;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var r: real;
    begin
      s := edit1.Text; //edit1中为要求值的表达式
      r := expr(); //  调用求值函数
      edit2.Text := floattostr(r); //将求值结果写到eidt2中
    end;function TForm1.cal(a, b: real; p: char): real;
    begin
      case p of
        '+': result := a + b;
        '-': result := a - b;
        '*': result := a * b;
        '/':
          begin
            if b = 0 then
            begin
              showmessage('除数为0');
              result := 0;
            end
            else
              result := a / b;
          end;
      end;
    end;function TForm1.comp(a, b: char): char;
    begin
      if not (a in ['+', '-', '*', '/', '(', ')', '#']) or not (b in ['+', '-', '*', '/', '(', ')', '#']) then result := 'e'
      else
        case a of
          '+', '-': case b of
              '*', '/', '(': result := '<';
            else result := '>';
            end;
          '*', '/': if b = '(' then result := '<' else result := '>';
          '(': if b = ')' then result := '=' else if b = '#' then result := 'e' else result := '<';
          ')': if b = '(' then result := 'e' else result := '>';
          '#': if b = ')' then result := 'e' else if b = '#' then result := 'R' else result := '<';
        end;
    end;
    function TForm1.expr(): real;
    var
      res, ch: char;
      oprTop, numTop: integer;
      opr: array[1..100] of char;
      num: array[1..100] of real;begin  opr[1] := '#';
      s := s + '#';
      oprTop := 1;
      numTop := 0;
      res := ' ';
      repeat
        if s[1] in ['0'..'9'] then
        begin
          inc(numTop);
          num[numTop] := GetNumber();
        end
        else
        begin
          ch := s[1];
          delete(s, 1, 1);
          repeat
            res := comp(opr[oprTop], ch);
            case res of
              '>': begin
                  num[numTop - 1] := cal(num[numTop - 1], num[numtop], opr[oprTop]);
                  dec(numTop);
                  dec(oprTop);
                end;
              '<': begin
                  inc(oprTop);
                  opr[oprTop] := ch;
                end;
              '=': begin
                  dec(oprTop);
                end;
              'e': begin
                  showmessage('表达式出错!');
                  result := 0;
                  exit;
                end;
              'R': begin
                  result := num[numTop];
                end;
            end;
          until res <> '>';
        end;
      until res = 'R';
    end;
    function TForm1.GetNumber(): real;
    var
      i, code: integer;
    begin
      i := 1;
      while (i <= length(s)) and (s[i] in ['0'..'9', '.']) do inc(i);
      val(copy(s, 1, i - 1), result, code);
      delete(s, 1, i - 1);
    end;
    end.
      

  2.   

    1:自己解析字串
    2﹕可以在sql語句中運算
    3﹕fastReport源碼fr_parse單元有個  TfrParser類,改改可用
      

  3.   

    给我Email + 30分,我将我所写的单元文件发给你,直接调用其中主函数即可。
      

  4.   

    随便连一个数据库
    写如下SQL
    select distinct(125+12*(123)/12) from yourtable
      

  5.   

    我的E-Mail:[email protected]
    要是帮的上忙 可以直接给我发短消息
      

  6.   

    select (125+12*(123)/12) as xxx;然后读xxx的值,:)
      

  7.   

    或者在GOOGLE里面输入:125+12*(123)/12=
      

  8.   

    function Calc(const Value:string):String;
    var
      vScript:variant;
      tmpString:string;
    begin
      Result:=Value;
      tmpString:=Value;
      vScript:=CreateOLEobject('ScriptControl');
      vScript.Language:='JavaScript';
      try
        try
          Result:=vScript.Eval(Value);
        finally
          vScript:=Unassigned;
        end;
      except
        Result:=tmpString;
      end;
    end;
      

  9.   

    做这些词法分析的东西最好用yacc,不要自己编写程序,否则词法一边头疼死
      

  10.   

    呵呵,我刚做过这个问题,就用的编译原理上的方法,设了两个堆栈,一个放数据,一个放操作符,自己设计了优先矩阵,又写了parseFloat和parseOperator两个函数,就解决了问题。麻烦是麻烦了一点,还是抛砖引玉吧。
    ==============================
    Unit1.pas
    =====================
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,CStack, Buttons, ExtCtrls;type
      TForm1 = class(TForm)
        Panel1: TPanel;
        SpeedButton1: TSpeedButton;
        SpeedButton2: TSpeedButton;
        SpeedButton3: TSpeedButton;
        SpeedButton5: TSpeedButton;
        SpeedButton6: TSpeedButton;
        SpeedButton7: TSpeedButton;
        SpeedButton8: TSpeedButton;
        SpeedButton9: TSpeedButton;
        SpeedButton10: TSpeedButton;
        SpeedButton11: TSpeedButton;
        SpeedButton12: TSpeedButton;
        SpeedButton13: TSpeedButton;
        SpeedButton14: TSpeedButton;
        SpeedButton15: TSpeedButton;
        SpeedButton16: TSpeedButton;
        SpeedButton17: TSpeedButton;
        SpeedButton18: TSpeedButton;
        SpeedButton19: TSpeedButton;
        SpeedButton20: TSpeedButton;
        Edit1: TEdit;
        SpeedButton21: TSpeedButton;
        procedure FormCreate(Sender: TObject);
        procedure SpeedButton5Click(Sender: TObject);
        procedure SpeedButton3Click(Sender: TObject);
        procedure SpeedButton21Click(Sender: TObject);
        procedure SpeedButton19Click(Sender: TObject);
        procedure SpeedButton20Click(Sender: TObject);
      private
        { Private declarations }
        start:boolean;
      public
        { Public declarations }
        function parseInt(var s:string):int64;
        function parseFloat(var s:string):double;
        function parseOperator(var s:string):char;    function doCalculation(data1,data2:double;op:char):double;
        procedure doStackCalculation(DStack:TFloatStack;OStack:TCharStack;op1,op2:Char);  end;
      TCharSet=set of Char;var
      Form1: TForm1;
      SNum:TCharSet=['0','1','2','3','4','5','6','7','8','9'];
      SOper:TCharSet=['+','-','*','/','(',')','='];  DataStack:TFloatStack;
      OperatorStack:TCharStack;
      Operator:string='+-*/()=';
      Operation:array [1..7,1..7] of integer
              =((1,1,2,2,2,1,1),(1,1,2,2,2,1,1),(1,1,1,1,2,1,1),(1,1,1,1,2,1,1),(2,2,2,2,2,3,4),
                (5,5,5,5,5,5,5),(2,2,2,2,2,2,5));
    implementation{$R *.dfm}
    procedure TForm1.doStackCalculation(DStack:TFloatStack;OStack:TCharStack;op1,op2:Char);
    //OStack栈顶为op1,新op为op1.
    var
      opn1,opn2,opn0:integer;
      data1,data2:double;
      op:char;
    begin
      opn1:=pos(op1,Operator);
      opn2:=pos(op2,Operator);
      opn0:=Operation[opn1,opn2];
      case opn0 of
        1: begin
              data2:=DStack.pop;
              data1:=DStack.pop;
              op:=OStack.pop;
              data1:=doCalculation(data1,data2,op);
              DStack.push(data1);
              doStackCalculation(DStack,OStack,OStack.getTop,op2);
            end;
        2: OStack.push(op2);
        3: OStack.pop;
        4: begin
              OStack.pop;
              doStackCalculation(DStack,OStack,OStack.getTop,op2);
            end;
      else ;
      end;
    end;function TForm1.doCalculation(data1,data2:double;op:char):double;begin
      case op of
        '+': result:=data1+data2;
        '-': result:=data1-data2;
        '*': result:=data1*data2;
        '/': if data2<>0 then result:=data1/data2
               else result:=0;
      end;
    end;function TForm1.parseInt(var s:string):int64;
    var
      temp:int64;
      len,i:integer;
    begin
      i:=1;
      result:=0;
      len:=length(s);
      while (i<=len) and (s[i] in SNum) do
        begin
          temp:=strtoint(s[i]);
          result:=result*10+temp;
          i:=i+1;
        end;
      s:=copy(s,i,len-i+1);
    end;function TForm1.parseFloat(var s:string):double;
    var
      temp,power:double;
      len,i:integer;
    begin
      i:=1;
      result:=0;
      len:=length(s);
      while (i<=len) and (s[i] in SNum) do
        begin
          temp:=strtoint(s[i]);
          result:=result*10+temp;
          i:=i+1;
        end;
      temp:=0;
      if s[i]='.' then
        begin
          power:=1;
          i:=i+1;
          while (i<=len) and (s[i] in SNum) do
            begin
              temp:=temp*10 + strtoint(s[i]);
              power:=power*10;
              i:=i+1;
            end;
          temp:=temp / power;
        end;
      result:=result+temp;
      s:=copy(s,i,len-i+1);
    end;
    function TForm1.parseOperator(var s:string):char;
    var
      len:integer;
    begin
      len:=length(s);
      if s[1] in SOper then
        begin
          result:=s[1];
          s:=copy(s,2,len-1);
        end
        else result:='#';
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      DataStack:=TFloatStack.Create;
      OperatorStack:=TCharStack.Create;
      start:=true;
      Edit1.Text:='0';
    end;
    procedure TForm1.SpeedButton5Click(Sender: TObject);
    begin
      if (Edit1.Text='0')or start then
        begin
          start:=false;
          Edit1.Text:=(Sender as TSpeedButton).Caption
        end
        else
          Edit1.Text:=Edit1.Text+(Sender as TSpeedButton).Caption;
    end;procedure TForm1.SpeedButton3Click(Sender: TObject);
    begin
    Edit1.Text:='0';
    end;procedure TForm1.SpeedButton21Click(Sender: TObject);
    var
      len:integer;
    begin
      len:=length(Edit1.Text);
      if len=1 then
        Edit1.Text:='0'
        else
          Edit1.Text:=copy(Edit1.Text,1,len-1);end;procedure TForm1.SpeedButton19Click(Sender: TObject);
    var
      s:string;
      data1:double;
      op:char;
      right,pushdata:boolean;
    begin
      Edit1.Text:=Edit1.Text+'=';
      start:=true;  s:=Edit1.Text;//  s:=s;
      right:=false;
      while s<>'' do
        begin
          data1:=parseFloat(s);
          op:=parseOperator(s);      if (op in ['(']) or right then
              pushdata:=false
            else pushdata:=true;
          if op in [')'] then
            right:=true
            else right:=false;      if pushdata then
            DataStack.push(data1);      doStackCalculation(DataStack,OperatorStack,OperatorStack.getTop,op);
        end;
      Edit1.Text:=floattostr(DataStack.pop);
    end;procedure TForm1.SpeedButton20Click(Sender: TObject);
    begin
      if Edit1.Text<>'0' then
        begin
          Edit1.Text:=Edit1.Text+(Sender as TSpeedButton).Caption;
          start:=false;
        end
        else
          if ((Sender as TSpeedButton).Caption='+')or((Sender as TSpeedButton).Caption='-') then
            begin
              Edit1.Text:='('+(Sender as TSpeedButton).Caption;
              start:=false;
            end;
    end;end.
      

  11.   

    =======================================
    CStack.pas
    ================
    unit CStack;interfacetype
      TFloatStack=class
        stack:array [0..127] of double;
        index:integer;
        empty:boolean;
        procedure push(value:double);
        function pop:double;
        function getTop:double;
        procedure Clear;
        function IsEmpty:boolean;
        function getTopIndex:integer;
        function getData(n:integer):double;    constructor Create;
      end;
      TCharStack=class
        stack:array [0..127] of Char;
        index:integer;
        empty:boolean;
        procedure push(value:Char);
        function pop:Char;
        function getTop:Char;
        procedure Clear;
        function IsEmpty:boolean;
        function getTopIndex:integer;
        function getData(n:integer):Char;    constructor Create;
      end;implementationconstructor TFloatStack.Create;
    begin
      inherited;
      index:=0;
      empty:=true;
    end;procedure TFloatStack.push(value:double);
    begin
      stack[index]:=value;
      index:=index+1;
      empty:=false;
    end;procedure TFloatStack.Clear;
    begin
      index:=0;
      empty:=true;
    end;function TFloatStack.pop:double;
    begin
      if IsEmpty then
        result:=0
        else
          begin
            index:=index-1;
            result:=stack[index];
            if index=0 then
              empty:=true;
          end;
    end;function TFloatStack.getTop:double;
    begin
      if not IsEmpty then
        result:=stack[index-1]
        else
          result:=0;
    end;function TFloatStack.IsEmpty:boolean;
    begin
      result:=empty;
    end;function TFloatStack.getTopIndex:integer;
    begin
      result:=index;
    end;function TFloatStack.getData(n:integer):double;
    begin
      result:=stack[n];
    end;///////////////////////////////////////////////////////////constructor TCharStack.Create;
    begin
      inherited;
      index:=0;
      empty:=true;
    end;procedure TCharStack.push(value:Char);
    begin
      stack[index]:=value;
      index:=index+1;
      empty:=false;
    end;procedure TCharStack.Clear;
    begin
      index:=0;
      empty:=true;
    end;function TCharStack.pop:Char;
    begin
      if IsEmpty then
        result:='='
        else
          begin
            index:=index-1;
            result:=stack[index];
            if index=0 then
              empty:=true;
          end;
    end;function TCharStack.getTop:Char;
    begin
      if not IsEmpty then
        result:=stack[index-1]
        else
          result:='=';
    end;function TCharStack.IsEmpty:boolean;
    begin
      result:=empty;
    end;function TCharStack.getTopIndex:integer;
    begin
      result:=index;
    end;function TCharStack.getData(n:integer):Char;
    begin
      result:=stack[n];
    end;end.
    =============================
      

  12.   

    object Form1: TForm1
      Left = 363
      Top = 162
      Width = 225
      Height = 340
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -19
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 24
      object Panel1: TPanel
        Left = 0
        Top = 0
        Width = 217
        Height = 313
        Caption = 'Panel1'
        TabOrder = 0
        object SpeedButton1: TSpeedButton
          Left = 8
          Top = 53
          Width = 50
          Height = 50
          Caption = '('
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton2: TSpeedButton
          Left = 58
          Top = 53
          Width = 50
          Height = 50
          Caption = ')'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton3: TSpeedButton
          Left = 108
          Top = 53
          Width = 50
          Height = 50
          Caption = 'AC'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton3Click
        end
        object SpeedButton5: TSpeedButton
          Left = 8
          Top = 103
          Width = 50
          Height = 50
          Caption = '1'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton6: TSpeedButton
          Left = 58
          Top = 103
          Width = 50
          Height = 50
          Caption = '2'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton7: TSpeedButton
          Left = 108
          Top = 103
          Width = 50
          Height = 50
          Caption = '3'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton8: TSpeedButton
          Left = 158
          Top = 103
          Width = 50
          Height = 50
          Caption = '/'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton20Click
        end
        object SpeedButton9: TSpeedButton
          Left = 8
          Top = 153
          Width = 50
          Height = 50
          Caption = '4'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton10: TSpeedButton
          Left = 58
          Top = 153
          Width = 50
          Height = 50
          Caption = '5'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton11: TSpeedButton
          Left = 108
          Top = 153
          Width = 50
          Height = 50
          Caption = '6'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton12: TSpeedButton
          Left = 158
          Top = 153
          Width = 50
          Height = 50
          Caption = '*'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton20Click
        end
        object SpeedButton13: TSpeedButton
          Left = 8
          Top = 203
          Width = 50
          Height = 50
          Caption = '7'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton14: TSpeedButton
          Left = 58
          Top = 203
          Width = 50
          Height = 50
          Caption = '8'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton15: TSpeedButton
          Left = 108
          Top = 203
          Width = 50
          Height = 50
          Caption = '9'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton16: TSpeedButton
          Left = 158
          Top = 203
          Width = 50
          Height = 50
          Caption = '-'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton20Click
        end
        object SpeedButton17: TSpeedButton
          Left = 8
          Top = 253
          Width = 50
          Height = 50
          Caption = '0'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton18: TSpeedButton
          Left = 58
          Top = 253
          Width = 50
          Height = 50
          Caption = '.'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton5Click
        end
        object SpeedButton19: TSpeedButton
          Left = 108
          Top = 253
          Width = 50
          Height = 50
          Caption = '='
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton19Click
        end
        object SpeedButton20: TSpeedButton
          Left = 158
          Top = 253
          Width = 50
          Height = 50
          Caption = '+'
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentFont = False
          OnClick = SpeedButton20Click
        end
        object SpeedButton21: TSpeedButton
          Left = 158
          Top = 53
          Width = 50
          Height = 50
          Caption = '←'
          OnClick = SpeedButton21Click
        end
        object Edit1: TEdit
          Left = 9
          Top = 10
          Width = 196
          Height = 30
          Ctl3D = False
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -19
          Font.Name = 'MS Sans Serif'
          Font.Style = []
          ParentCtl3D = False
          ParentFont = False
          ReadOnly = True
          TabOrder = 0
          Text = '123456789012345678'
        end
      end
    end