可以没有用数这个数据结构,可以用子程序递归的栈来模拟数。
要注意的方面:
- 先要给运算符一个等级
一般:
+-:1
*/:2
^:3
~(负号):4
():5
num:6
负号要和减号要分开,在数字和)后面的是减号,在其他符号后面的是负号 - 扫描的时候要跳过括号
比如1×(1+2)×3
要跳过括号,否则将选择+ - 扫描字符串的时候,要倒着扫描(运算等级判断用<和>)。
比如: 2/3×4
顺着扫描的话,会最终指向2/3的/,则计算会变成2/(3×4),显然是错误的。
倒着搜的话,最指向×,即计算为(2/3)×4;
下面是代码:
var
expr:string;
function is_num(a:char):boolean;
begin
if(a>='0')and(a<='9')then exit(true) else exit(false);
end;
function init(a:string):string;
var
b:string;
i:longint;
t:boolean;
begin
b:='';
for i:=1 to length(a) do
if a[i]<>' ' then b:=b+a[i];
t:=true;
for i:=1 to length(b) do begin
if b[i]='-' then begin
if t then b[i]:='~';
t:=true;
end else
if is_num(b[i])or (b[i]=')') then t:=false else t:=true;
end;
exit(b);
end;
function pow(a,b:longint):longint;
var i:longint;
begin
if a=0 then exit(0);
if b=0 then exit(1);
pow:=1;
for i:=1 to b do pow:=pow*a;
end;
function work(a:string):longint;
var
i,len,r,lev,p1,p2:longint;
d:double;
c:char;
begin
len:=length(a);
lev:=6;
c:='1';
r:=0;
for i:=len downto 1 do begin
if a[i]=')' then begin
if (r=0)and(lev>5) then begin
lev:=5;
p2:=i;
c:='$';
end;
inc(r);
end;
if a[i]='(' then begin
dec(r);
if (r=0)and(lev=5) then p1:=i;
end;
if r=0 then
case a[i] of
'+':if lev>1 then begin lev:=1;p1:=i;c:='+';end;
'-':if lev>1 then begin lev:=1;p1:=i;c:='-';end;
'*':if lev>2 then begin lev:=2;p1:=i;c:='*';end;
'/':if lev>2 then begin lev:=2;p1:=i;c:='/';end;
'^':if lev>3 then begin lev:=3;p1:=i;c:='^';end;
'~':if lev>4 then begin lev:=4;p1:=i;c:='~';end;
end;
end;
if c='+' then exit(work(copy(a,1,p1-1))+work(copy(a,p1+1,len-p1)));
if c='-' then exit(work(copy(a,1,p1-1))-work(copy(a,p1+1,len-p1)));
if c='*' then exit(work(copy(a,1,p1-1))*work(copy(a,p1+1,len-p1)));
if c='/' then exit(trunc(work(copy(a,1,p1-1))/work(copy(a,p1+1,len-p1))));
if c='^' then exit(pow(work(copy(a,1,p1-1)),work(copy(a,p1+1,len-p1))));
if c='~' then exit(0-work(copy(a,2,len-1)));
if c='$' then exit(work(copy(a,p1+1,p2-p1-1)));
if c='1' then begin val(a,d);exit(trunc(d));end;
end;
begin
readln(expr);
expr:=init(expr);
writeln(work(expr));
end.