zoukankan      html  css  js  c++  java
  • 第一篇《后缀表达式》

    插图


    注释说明
            开发平台 Delphi 7
            本程序主要说明如何把一个普通的算术表达式(中缀表达式)转换为后缀表达式,并计算出结果。参考《数据结构与算法分析——C语言描述》第二版 3.3.3节
            后缀表达式相关内容
    主要代码

    unit Suffixer;

    interface
    uses
      SysUtils;
    Type
      TSuffixExpositor = class;//将一个字符串数学表达式解析成后缀表达式
      TSuffixExecuter  = class;//计算后缀表达式的值

      TSuffixExpositor = class
      private
        FMathExpression: PChar;
        procedure SetMathExpression(const Value: PChar);
        function Expositor:string; //解析
      public
        constructor Create();
        destructor  Destroy();override;
        property  MathExpression:PChar read FMathExpression write SetMathExpression;
        property  SuffixExpression:string read Expositor;
      end;

      TSuffixExecuter  = class
      private
        FSuffixExpression: PChar;
        procedure SetSuffixExpression(const Value: PChar);
        function  getValue():Extended;
      public
        property SuffixExpression:PChar write SetSuffixExpression;
        property Value:Extended read getValue;
      end;
     
    implementation

    { TSuffixExpositor }

    constructor TSuffixExpositor.Create;
    begin

    end;

    destructor TSuffixExpositor.Destroy;
    begin

      inherited;
    end;

    function TSuffixExpositor.Expositor:string;
    Type
      TPRI = (PRIUnknown=0,PRII,PRIII,PRIIII,PRIIV);
    var
      CharIndex:Integer;
      Stack:array[0..20] of Char;
       
      function PRI(aChar:Char):TPRI; //取得优先级
      begin
        case aChar of
          '+','-':Result:=PRII;
          '*','/':Result:=PRIII;
    //      '(',')':Result:=PRIIII;
    //      '[',']':Result:=PRIIV;
          else
            Result:=PRIUnknown;
    //        Raise Exception.Create('操作符有误!');
        end;
      end;

      function getBracket(aChar:Char):Char; //取得对应的开括号
      begin
        case aChar of
          ')':Result:='(';
          ']':Result:='[';
        else
          Raise Exception.Create('操作符有误!');
        end;
      end;

      function Bracket():string;  //闭合括号
      var
        i:Integer;
        Target:Char;
      begin
        Result:='';
        Target:=getBracket(FMathExpression^);
        for i:= CharIndex downto Low(Stack) do
        begin
          if Stack[i] = Target then
          begin
            CharIndex:=i-1;
            Break; 
          end;
           Result:=Result + Stack[i];
        end;
      end;

      function getHigherSymbols(aChar:Char):string;//顺次取得栈中所有比当前操作符优先级高的操作符
      var
        i:Integer;
        aPRI:TPRI;
      begin
        aPRI:=PRI(aChar);
        for i:= CharIndex downto Low(Stack) do
        begin
          if PRI(Stack[i]) >= aPRI then
            Result:=Result + Stack[i]
          else
            Break;
          CharIndex:=i;//重新设置指针
        end; 
      end;

      function getLeftSymbols():string; //将栈中剩余的操作符全部取出
      var
        i:Integer;
      begin
        Result:='';
        for i:=CharIndex downto Low(Stack) do
          Result:=Result +Stack[i];
      end; 

      procedure PushStack(const IncIndex:Boolean=True);
      begin
        Inc(CharIndex,Integer(IncIndex));
        Stack[CharIndex]:=FMathExpression^;
      end; 

    begin
      CharIndex:=-1;
      while FMathExpression^ <> #0 do
      begin
        case FMathExpression^ of
          '(','[':begin//只入栈 [这里是否需要判断优先级]
                    PushStack;
                  end;
          '0'..'9','a'..'z','A'..'Z': begin  //一个操作数,放到输出中
                      Result:=Result+FMathExpression^;
                    end;
          '+','-','*','/':begin//一个操作符
                          //检查一下新的操作符与栈中的最顶上的哪个优先级高,若顶的优先级高,则需要将顶的操作符一起放到输出中
                            if CharIndex > -1 then//确保栈中有数据
                            begin
                              if PRI(Stack[CharIndex]) >= PRI(FMathExpression^) then//栈顶优先级高
                              begin
                                Result:=Result+ getHigherSymbols(FMathExpression^);
                                PushStack(False);//将操作符入栈
                              end
                              else
                                PushStack;
                            end
                            else //需要入栈
                              PushStack;
                          end;
          ')',']':begin//一个闭合符
                    Result:=Result + Bracket;
                  end;
          else
            Raise Exception.Create('数学表达式中包含非法字符   '+ QuotedStr(FMathExpression^) +'      ');
        end;
        Inc(FMathExpression);
      end;
      Result:=Result + getLeftSymbols;
    end;

    procedure TSuffixExpositor.SetMathExpression(const Value: PChar);
    begin
      FMathExpression := Value;
    end;


    { TSuffixExecuter }

    function TSuffixExecuter.getValue: Extended;
    var
      Stack:array[0..20] of Extended;
      StackIndex:Integer;

      procedure PushStack(const IncIndex:Boolean=True);
      begin
        Inc(StackIndex,Integer(IncIndex));
        Stack[StackIndex]:=StrToFloat(FSuffixExpression^);
      end;  

      function MidValue():Extended;
      begin
        Result:=0;
        case FSuffixExpression^ of
          '+':begin
                if StackIndex >0 then
                  Result:=Stack[StackIndex] + Stack[StackIndex-1]
                else
                  Result:=Stack[StackIndex];
              end;
          '-':begin
                if StackIndex >0 then
                  Result:=Stack[StackIndex-1] - Stack[StackIndex]
                else
                  Result:=Stack[StackIndex];
              end;
          '*':begin
                if StackIndex >0 then
                  Result:=Stack[StackIndex] * Stack[StackIndex-1]
                else
                  Result:=Stack[StackIndex];
              end;
          '/':begin
                if StackIndex >0 then
                  Result:=Stack[StackIndex-1] / Stack[StackIndex]
                else
                  Result:=Stack[StackIndex];
              end;
         end;
         Dec(StackIndex,1);
         Stack[StackIndex]:=Result;//怎么入栈
      end;

    begin
      StackIndex:=-1;
      Result:=0;
      while FSuffixExpression^ <>#0 do
      begin
        case FSuffixExpression^ of
          '0'..'9': begin
                      PushStack;
                    end;
          'a'..'z','A'..'Z':begin
                            //这里需要填入数值
                            end;
          '+','-','*','/':begin //将结果入栈
                            Result:=MidValue;
                          end;
          else
            Raise Exception.Create('后缀表达式含有非法字符  '+FSuffixExpression^+'    ');
        end;
        Inc(FSuffixExpression);
      end;
    end;

    procedure TSuffixExecuter.SetSuffixExpression(const Value: PChar);
    begin
      FSuffixExpression := Value;
    end;

    end.



    要点
           1、普通数学表达式到后缀表达式的转换
           2、栈的使用


    源文件
    /Files/goldli/MathExpression.rar


  • 相关阅读:
    【转载】MDX 去年当月值、差值、同比
    【原创】Analyzer安全性异常(应用程序视图执行安装策略不允许的操作)
    Analyzer普通用户登录不了[从网络访问此计算机]
    【转载】51CTO如何防止SQL注入的解决方法
    【转载】51CTOAndroidManifest.xml文件详解
    Eclipse插件安装方式
    Typemock揭示 安装其它三方软件可能引起冲突,那试试不安装直接引用它的DLL
    项目从VS2010 升 VS2012 遇到的代表性问题及解决
    c# comboBox模糊匹配
    sqlJDBC安装使用
  • 原文地址:https://www.cnblogs.com/goldli/p/1493336.html
Copyright © 2011-2022 走看看