关于计算字符的解析(200分)

  • 主题发起人 主题发起人 daidai97271128
  • 开始时间 开始时间
D

daidai97271128

Unregistered / Unconfirmed
GUEST, unregistred user!
我要一个计算字符的解析的原程序
要求能处理小括号与+,-,*,/与小数点的四侧运算即可
 
下面为我作的模拟栈的字符串解析文件,能满足你的需要,
unit strafununit;
interface
uses dialogs,
sysutils;
type
TdouarrAy = array of do
uble;
//声明数值栈类型
Toperset = set of char;//声明操作符集合
{数值栈和操作符栈的入栈函数}
{Soper为当前的操作符栈,Coper为要压入的操作符}
function OperPush(var Soper:string;Coper:char):boolean;overload;
{Sdata为当前的数值栈,Cdata为要压入的数值}
function OperPush(var Sdata:TdouarrAy;Cdata:double):boolean;overload;
{数值栈和操作符栈的出栈函数,其它同上}
function OperPop(var Soper:string;var Coper:char):boolean;overload;
function OperPop(var Sdata:TdouarrAy;var Cdata:double):boolean;overload;
{运算判断函数,fdata为前面的数值,moper为中间的操作符,
bdata为后面的数值、返回运算后的数值}
function OperDiag(fdata:double;moper:char;bdata:double):double;
{数值栈和操作符栈的得到栈顶元素的函数}
function GetTopOper(Soper:string):char;overload;
function GetTopOper(Sdata:TdouarrAy):double;overload;
{操作符优先级比较函数,Foper为前面的操作符,Boper为后面的操作符}
function PriComp(Foper:char;Boper:char):char;
{从输入字符串中截取数值或操作符函数}
function GetData(var Toper:string):string;
{操作符字符串解析主函数}
function StrAnalysis( var Toper:string):double;
implementation
{操作符栈入栈出栈函数}
function OperPush(var Soper:string;Coper:char):boolean;
begin
soper:=soper+coper;//当前操作符压入操作符栈顶
result:=true;
end;
function OperPop(var Soper:string;var Coper:char):boolean;
var slen:integer;
begin
slen:=length(Soper);
Coper:=Soper[slen];//弹出操作符栈顶操作符
Soper:=copy(Soper,1,slen-1);
result:=true;
end;
{数值栈入栈出栈函数}
function OperPush(var Sdata:TdouarrAy;Cdata:double):boolean;
var dlen:integer;
begin
dlen:=length(Sdata);
setlength(Sdata,dlen+1);
Sdata[dlen]:=Cdata;//当前数值入栈
result:=true;
end;
function OperPop(var Sdata:TdouarrAy;var Cdata:double):boolean;
var dlen:integer;
begin
dlen:=length(Sdata);
Cdata:=sdata[dlen-1];//当前数值出栈
Sdata:=copy(Sdata,0,dlen-1);//栈顶下移
result:=true;
end;
{运算判断函数,fdata为前面的数值,moper为中间的操作符,
bdata为后面的数值、返回运算后的数值}
function OperDiag(fdata:double;moper:char;bdata:double):double;
begin
case moper of
'+':result:=bdata+fdata;
'-':result:=bdata-fdata;
'*':result:=bdata*fdata;
'/':try
result:=bdata/fdata;
except
showmessage('错误!除数不能为零');
result:=0;
//除数为零时的异常处理
end;
else
begin
showmessage('错误!无此操作符');
result:=0;
end;
end;
end;
{操作符栈的得到栈顶元素的函数}
function GetTopOper(Soper:string):char;
var slen:integer;
begin
slen:=length(Soper);
result:=Soper[slen];// 得到栈顶操作符
end;
{数值栈得到栈顶元素的函数}
function GetTopOper(Sdata:TdouarrAy):double;
var slen:integer;
begin
slen:=length(Sdata);
result:=Sdata[slen-1];//得到栈顶数值
end;
{操作符优先级比较函数,Foper为前面的操作符,Boper为后面的操作符}
function PriComp(Foper,Boper:char):char;
var coper:toperset;
begin
Coper:=['+','-','*','/','#','(',')'];
{操作符优先级比较}
if (Foper in coper)and(Boper in coper) then
begin
case foper of
'+':begin
{'+'优先级低于 '*','/','(' }
if (Boper='*')or(Boper='/')or(Boper='(')then
result:='<'
else
result:='>';
end;
{'-'优先级低于 '*','/','(' }
'-':begin
if (Boper='*')or(Boper='/')or(Boper='(')then
result:='<'
else
result:='>';
end;
{'*'优先级低于 '(' }
'*':begin
if Boper='('then
result:='<'
else
result:='>';
end;
{'/'优先级低于 '(' }
'/':begin
if Boper='('then
result:='<'
else
result:='>';
end;
{ '('碰到 ')' 则输出去括号标志‘=’}
'(':begin
if Boper=')'then
result:='='
else
result:='<';
end;
{')'优先级最高}
')':result:='>';
{‘#’为字符串开始与结束标志位}
'#':begin
if Boper='#'then
result:='='
else
result:='<';
end;
else
begin
showmessage('错误,字符串输入有误!');
result:='x';
end;
end;
end
else
begin
showmessage('错误,字符串中有操作符以外的字符!');
result:='x';
end;
end;
{从输入字符串中截取数值或操作符函数}
function getdata(var Toper:string):string;
var
operset:Toperset;
tstr:string;
i,TempLength:integer;
begin
i:=1;
tstr:='';
operset:=['+','-','*','/','(',')','#'];//操作符集
{如果是操作符则截取操作符}
if Toper[1] in operset then
begin
result:=Toper[1];
TempLength:=length(Toper);
Toper:=copy(Toper,2,TempLength-1);
{如果是数值则截取数值}
end
else
while not(Toper in operset) do
begin
tstr:=tstr+Toper;
i:=i+1;
end;
if tstr<>'' then
begin
result:=tstr;
Toper:=copy(Toper,length(tstr)+1,length(Toper)-length(tstr));
//字符串中截去取出的部分
end;
end;
{操作符字符串解析主函数}
function StrAnalysis(var Toper:string):double;
var operset:Toperset;//操作符集
sdata:TdouarrAy;//数值栈
soper:string;//操作符栈
getstr:string;//存放从字符串中截取操作符和数值的临时变量
theta:char;// 存放操作符的临时变量
do
udataf:double;//存放数值的临时变量
do
udatar:double;//存放数值的临时变量
begin
{初始化栈及数据}
setlength(sdata,0);//初始化数值栈
soper:='';//初始化操作符栈
operset:=['+','-','*','/','(',')','#'];
//定义操作符集
doudataf:=0;
doudatar:=0;
theta:=' ';
Toper:='#'+Toper+'#';//给字符串加上开始和结束标志符
{因为OperPush函数后面的参数为char型所以写成GetData(Toper)[1]}
OperPush(soper,GetData(Toper)[1]);//先把‘#’入栈
getstr:=GetData(Toper);//得到 ‘#’ 后的第一个数值或操作符
{‘#’与‘#’未碰到既字符串未处理完}
while(getstr<>'#')or(GetTopOper(soper)<>'#') do
begin
{因为operset是char集所以写成getstr[1}
if not(getstr[1] in operset) then
//如果不是操作符则如数值栈
begin
OperPush(sdata,strtofloat(getstr));
getstr:=GetData(Toper);//取下一数值或操作符
end
else
// 如果是操作符则与操作符栈顶元素先比较优先级
case pricomp(GetTopOper(soper),getstr[1]) of
'<': begin
//如果是操作符栈顶元素优先级低则直接入操作符栈
OperPush(soper,getstr[1]);
getstr:=GetData(Toper);//取下一数值或操作符
end;
'=':begin
//如果是’=‘则脱括号
OperPop(soper,theta);
getstr:=GetData(Toper);//取下一数值或操作符
end;
'>':begin
//如果是操作符栈顶元素优先级高则先计算,不用取下一数值或操作符
OperPop(soper,theta);
OperPop(sdata,doudataf);
OperPop(sdata,doudatar);
OperPush(sdata,OperDiag(doudataf,theta,doudatar));
//运算结果入栈
end;
end;
end;
result:=GetTopOper(sdata);//返回结果既数值栈的栈顶元素
end;
end.
不懂林系我:zswenyun@163.com
 
接受答案了.
 
后退
顶部