第一篇《后缀表达式》

插图


注释说明
        开发平台 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


posted @ 2009-06-01 06:52  (大贤者模式)  阅读(2167)  评论(5编辑  收藏  举报