怎样判定表达式是否正确?(50分)

  • 主题发起人 主题发起人 yayiye
  • 开始时间 开始时间
Y

yayiye

Unregistered / Unconfirmed
GUEST, unregistred user!
有一个字符串表达式 ,只包含+,-,*,/ 和()
例如 s:='10-2*(2-1)+3/(3-2)' 正确
s1:='123-((asdf-9*****abb )' 不正确
怎样判定这个表达式是否正确(合法)?不一定要计算出结果
除了使用编译原理,有什么其它方法?
 
这可是个大procedure呢。
没几百行code,搞不掂吧。

要判断括号(左右口号个数,括号前后是否为数字或者是括号),
符号的前后……

等等。
 
是阿,
我本来想用堆栈的方法,写一个词法分析器,但是时间紧迫
谁能帮帮忙?最少200分 ,i can promise
 
如果没有办法 我只能用最苯的了试一试了
s:='123-((asdf-9*****abb'
with Query1 do
begin
Sql.add('select '+s+' from table');
try
Open;
except
..............
end;
end;
请问有人由其他办法吗?
 
网上有现成的计算函数的,找找啊
 
另类算法,不知行得通吗,你去试试。。。嘻
function a(s:string):boolean;
var s1,c:string;i,cn1,cn2:integer;
begin
s1:='0123456789+-*/()';
c:='';cn1:=0;cn2:=0;
for i:=1 to length(s) do
begin
p;=pos(s,s);
case p of
1-10:c:=c+'1';
11-14:c:=c+'2';
15:begin c:=c+'3';cn1:=cn1+1;end;
16:begin c:=c+'4';cn2:=cn2+1;end;
end;
'10-2*(2-1)+3/(3-2)
if pos('22',c)>0 then result:=false;
if pos('34',c)>0 then result:=false;
if pos('32',c)>0 then result:=false;
if pos('24',c)>0 then result:=false;
if cn1<>cn2 then result:=false;
result:=true;
end;
 
'10-2*(2-1)+3/(3-2)这行是多余的。。。。呵
 
突然又发现一个问题,重新改过。。。哈
function a(s:string):boolean;
var s1,c:string;i,cn1,cn2:integer;
begin
s1:='0123456789+-*/()';
c:='';cn1:=0;cn2:=0;
for i:=1 to length(s) do
begin
p;=pos(s,s);
case p of
1-10:c:=c+'1';
11-14:c:=c+'2';
15:begin c:=c+'3';cn1:=cn1+1;end;
16:begin c:=c+'4';cn2:=cn2+1;end
else result:=false;
end;
if pos('22',c)>0 then result:=false;
if pos('34',c)>0 then result:=false;
if pos('32',c)>0 then result:=false;
if pos('24',c)>0 then result:=false;
if cn1<>cn2 then result:=false;
result:=true;
end;
 
方法1,导入MSScriptControl控件,让控件执行表达式,如果发生异常,
则表示表达式有问题。

方法2,要利用数据库,用connection执行'select ' + [表达式],如果发生异常,
则表示表达式有问题。
 
一年前写的,有点冗长,本来不想拿出来的!:》
你高兴忙我优化优化!字符串表达式 ,只包含+,-,*,/ 和()
function Check_BiaoDaShi(BiaoDaShi: string): Boolean;
var
I, J: Integer;
KuoHao: Integer;
begin
KuoHao := 0;
for I := 1 to Length(BiaoDaShi) do
begin
if BiaoDaShi = '(' then
KuoHao := KuoHao + 1
else
if BiaoDaShi = ')' then
begin
if KuoHao <= 0 then
begin
ShowMessage('对不起,少左括号!');
Result := False;
Exit;
end
else
KuoHao := KuoHao - 1;
end
else
if BiaoDaShi = '/' then //判断除数不能为0
begin
for J := I + 1 to Length(BiaoDaShi) do
begin
if not (BiaoDaShi[J] in ['0'..'9', '.']) then
begin
if StrToCurr(Copy(BiaoDaShi, I + 1, J - I - 1)) = 0 then
begin
Showmessage('对不起,除数不能为0!');
Exit;
end
else
Break;
end
else
if J = Length(BiaoDaShi) then
begin
if StrToCurr(Copy(BiaoDaShi, I + 1, J - I)) = 0 then
begin
Showmessage('对不起,除数不能为0!');
Exit;
end;
end;
end;
end;
if (I = Length(BiaoDaShi)) and (KuoHao > 0) then
begin
ShowMessage('对不起,少右括号!');
Result := False;
Exit;
end;
if I = 1 then
begin
if not (BiaoDaShi in ['0'..'9', '(', '.']) then
begin
ShowMessage('对不起,表达式不能以操作符开头!');
Result := False;
Exit;
end;
end
else
if I = Length(BiaoDaShi) then
begin
if not (BiaoDaShi in ['0'..'9', ')', '.']) then
begin
ShowMessage('对不起,表达式不能以操作符结尾!');
Result := False;
Exit;
end;
end
else
if ((BiaoDaShi = '+') or (BiaoDaShi = '-') or (BiaoDaShi = '*') or (BiaoDaShi = '/') or (BiaoDaShi = ')') or (BiaoDaShi = '.'))
and ((BiaoDaShi[I - 1] = '+') or (BiaoDaShi[I - 1] = '-') or (BiaoDaShi[I - 1] = '*') or (BiaoDaShi[I - 1] = '/') or (BiaoDaShi[I - 1] = '(') or (BiaoDaShi[I - 1] = '.')) then
begin
if (BiaoDaShi = '.') and (BiaoDaShi[I - 1] = '.') then
ShowMessage('对不起,当前系统不认两个连续的..符号!')
else
if (BiaoDaShi = ')') and (BiaoDaShi[I - 1] = '(') then
// ShowMessage('当前表达式中有冗余的括号,但不影响执行结果!')
else
begin
if BiaoDaShi = ')' then
ShowMessage('对不起,右括号前或左括号后不可直接有操作符!')
else
if BiaoDaShi[I - 1] = '(' then
ShowMessage('对不起,右括号前或左括号后不可直接跟操作符!')
else
ShowMessage('对不起,操作符之间必须有数值分隔!');
end;
Result := False;
Exit;
end;
end;
Result := True;
end;
 
to rjiajia:
你这个函数有问题吧,Result永远为True呀!
Pascal不象别的语言,函数里Result赋值后还会向下执行的,
我改了一下:^_^

function a(s: string): boolean;
var
s1, c : string;
p, i, cn1, cn2: integer;
begin
result := false;

s1 := s;
c := '';
cn1 := 0;
cn2 := 0;
for i := 1 to length(s) do
begin
p := pos(s, s);
case p of
1 - 10: c := c + '1';
11 - 14: c := c + '2';
15:
begin c := c + '3';
cn1 := cn1 + 1;
end;
16:
begin c := c + '4';
cn2 := cn2 + 1;
end
else Exit;
end;
if pos('22', c) > 0 then
Exit;
end;
if pos('34', c) > 0 then Exit;
if pos('32', c) > 0 then Exit;
if pos('24', c) > 0 then Exit;
if cn1 <> cn2 then Exit;
result := true;
end;
 
错了错了:
function a(s: string): boolean;
var
s1, c : string;
p, i, cn1, cn2: integer;
begin
result := false;

s1 := '0123456789+-*/()';
c := '';
cn1 := 0;
cn2 := 0;
for i := 1 to length(s) do
begin
p := pos(s, s);
case p of
1 - 10: c := c + '1';
11 - 14: c := c + '2';
15:
begin c := c + '3';
cn1 := cn1 + 1;
end;
16:
begin c := c + '4';
cn2 := cn2 + 1;
end
else Exit;
end;
if pos('22', c) > 0 then
Exit;
end;
if pos('34', c) > 0 then Exit;
if pos('32', c) > 0 then Exit;
if pos('24', c) > 0 then Exit;
if cn1 <> cn2 then Exit;
result := true;
end;
 
先转成逆波兰式再判断。源代码在http://www.tommstudio.com中可以找到。
 
经过我的调试,结果完全正确
function TForm1.a(s:string):boolean;
var s1,c:string;p,i,cn1,cn2:integer; r:boolean;
begin
r:=true;
s1:='1234567890+-*/()';
c:='';cn1:=0;cn2:=0;
for i:=1 to length(s) do
begin
p:=pos(s,s1);
case p of
0:r:=false;
1..10:c:=c+'1';
11..14:c:=c+'2';
15:begin c:=c+'3';cn1:=cn1+1;end;
16:begin c:=c+'4';cn2:=cn2+1;end ;
end;
end;
if c[1]='2' then r:=false;
if c[length(c)]='2' then r:=false;
if pos('22',c)>0 then r:=false;
if pos('34',c)>0 then r:=false;
if pos('32',c)>0 then r:=false;
if pos('24',c)>0 then r:=false;
if pos('13',c)>0 then r:=false;
if pos('41',c)>0 then r:=false;
if cn1<>cn2 then r:=false;
result:=r;
end;
 
我同意WWW的,这是数据结构里基本的东西,何必那么费劲
 
to: rjiajia
我加了个小数点
function a(s: string): boolean;
var s1,c:string;p,i,cn1,cn2:integer; r:boolean;
begin
r:=true;
s1:='1234567890+-*/().';
c:='';cn1:=0;cn2:=0;
for i:=1 to length(s) do
begin
p:=pos(s,s1);
case p of
0:r:=false;
1..10:c:=c+'1';
11..14:c:=c+'2';
15:begin c:=c+'3';cn1:=cn1+1;end;
16:begin c:=c+'4';cn2:=cn2+1;end ;
17:c:=c+'5';
end;
end;
if c[1] in ['2','5'] then
r:=false;
if c[length(c)] in ['2','5'] then
r:=false;
if (pos('25',c)>0) or (Pos('35',c)>0) or (Pos('45',c)>0) then
r:=false;
if (pos('52',c)>0) or (Pos('53',c)>0) or (Pos('54',c)>0) then
r:=false;
if pos('22',c)>0 then
r:=false;
if pos('34',c)>0 then
r:=false;
if pos('32',c)>0 then
r:=false;
if pos('24',c)>0 then
r:=false;
if pos('13',c)>0 then
r:=false;
if pos('41',c)>0 then
r:=false;
if cn1<>cn2 then
r:=false;
result:=r;
end;
谢谢大家参与!
 
最好再加个 if pos('43',c)>0 then r:=false;
该给分了吧。。。嘻
 
分数马上补
 
多人接受答案了。
 
后退
顶部