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