中序转后序算法完成简易计算器的delphi实现

来源:互联网 发布:flash课件制作软件 编辑:程序博客网 时间:2024/05/24 02:35

之前看网上有C++版的,python版的,貌似没有delphi版的,写了一个贴上来以供参考:

unit Unit1;


interface


uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Contnrs, RegularExpressions;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;


implementation


{$R *.dfm}


//运算符优先级
function priority(op: string) :Integer;
begin
  if (op='+') or (op='-') then result:=1
  else
  if (op='*') or (op='/') then result:=2
  else
  Result:=0;
end;
//中序转后序
function toPostfix(sList: TStringList): TStringList;
var
  pList: TStringList;
  sb: TStringBuilder;
  stack: Tstack;
  str:string;
begin
  pList:= TStringList.Create;
  sb:= TStringBuilder.Create;
  stack:= Tstack.Create;
  str:='#';
  stack.Push(pointer(str));
  for str in sList do
  begin
    if str = '(' then stack.Push(pointer(str))
    else
    if priority(str)>0 then
    begin
      while priority(string(stack.Peek))>=priority(str) do
      begin
        pList.Add(string(stack.pop));
      end;
      stack.Push(pointer(str));
    end
    else
    if str = ')' then
    begin
      while (string(stack.Peek) <> '(') and (string(stack.Peek) <> '#') do
      begin
        pList.Add(string(stack.pop));
      end;
      stack.pop;
    end
    else
    begin
      pList.Add(str);
    end;
  end;
  while string(stack.Peek) <> '#' do
  begin
    pList.Add(string(stack.pop));
  end;
  result:=pList;
end;


//解析中序字符串为中序字符串数组(验证通过)
function str2arr(Str: string) :TStringList;
const
  Pattern='\(|\+|\-|\*|/|\)';
var
  reg:TRegEx;
  match:TMatch;
  sList: TStringList;
  s: string;
  n: Integer;
begin
  n:=1;
  sList:=TStringList.Create;                              //n代表数字长度
  reg:=TRegEx.Create(Pattern);
  match:=reg.Match(Str);
  while match.Success do                                  //成功了
  begin
    if match.Index-n>0 then                               //两个操作符不相邻
    begin
      sList.add(Copy(Str,n,match.Index-n));               //copy()从下标1开始
    end;
    sList.add(Copy(Str,match.Index,1));
    n:=match.Index+1;
    match:=match.NextMatch;
  end;
  if not match.Index=Length(Str) then
  begin
    sList.add(Copy(Str,match.Index+1,Length(str)-match.Index+1));
  end;
  result:=sList;
end;


//计算后序表达式
function calPostfix(sList: TStringList) :string;
var
  left,right: integer;
  stack: Tstack;
  s: string;
begin
  stack:= Tstack.Create;
  for s in sList do
  begin
    stack.Push(pointer(s));
    if s='+' then
    begin
      stack.pop;
      right:=Strtoint(string(stack.pop));
      left:=Strtoint(string(stack.pop));
      stack.Push(pointer(inttostr(left+right)));
    end;
    if s='-' then
    begin
      stack.pop;
      right:=Strtoint(string(stack.pop));
      left:=Strtoint(string(stack.pop));
      stack.Push(pointer(inttostr(left-right)));
    end;
    if s='*' then
    begin
      stack.pop;
      right:=Strtoint(string(stack.pop));
      left:=Strtoint(string(stack.pop));
      stack.Push(pointer(inttostr(left*right)));
    end;
    if s='/' then
    begin
      stack.pop;
      right:=Strtoint(string(stack.pop));
      left:=Strtoint(string(stack.pop));
      if right<>0 then
      stack.Push(pointer(inttostr(left div right)));
    end;
  end;
  result:=string(stack.pop);
end;




procedure TForm1.Button1Click(Sender: TObject);
var
  str:string;
  pList:TStringList;
begin
  Memo1.Clear;
  pList:=toPostfix(str2arr('('+Edit1.Text+')'));
  Memo1.Lines.Add('中序转后序表达式:');
  Memo1.Lines.Add(pList.Text);


  Memo1.Lines.Add('pList长度:'+inttostr(pList.Count));


  str:=calPostfix(pList);
  Memo1.Lines.Add('后序表达式计算结果:');
  Memo1.Lines.Add(str);
  Edit1.Text:=Edit1.Text+'='+str;


  FreeAndNil(pList);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Clear;
  Memo1.ScrollBars:=ssVertical;
  Memo1.Lines.Add('表达式未做正确性效验,请自行检查');
end;


end.

阅读全文
0 0