计算字符串中数值的问题!!!!(50分)

  • 主题发起人 主题发起人 szh8181
  • 开始时间 开始时间
S

szh8181

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在需要计算一字符串中的数值
如 s:string;
s:='1+2*3';
我需要得出s中的计算结果 i:=7;
请各位大虾指教!!!多谢!!!!!!!!
 
1.使用SQL语句代替计算:简单(等一下给你),前提是SQL要认识
2.使用自己写的函数计算:麻烦
 
简单的计算没有问题:
//需要去掉表达式中的逗号,小数点属于数字部分
function TForm4.DefineCalculate(Source:String):TStringList;
var S,ST:String;
i:Integer;
LB:Boolean;
SL:TStringList;
begin
SL:=TStringList.Create;
S:='';
LB:=True;//默认当前属于数字部分
for i:=1 to Length(Source) do begin
ST:=Source;
if Pos(ST,'0123456789.')=0 then begin
if LB then begin
if S<>'' then SL.Add(S);
S:=ST;LB:=False;
end else begin
S:=S+ST;
end;
end else begin
if LB then begin
S:=S+ST;
end else begin
if S<>'' then SL.Add(S);
S:=ST;LB:=True;
end;
end;
end;
if S<>'' then SL.Add(S);
Result:=SL;
end;
procedure TForm4.Button6Click(Sender: TObject);
var S,SQL:String;
i:Integer;
SL:TStringList;
begin
SL:=DefineCalculate('1+2*3');
if SL.Count=0 then exit;
SQL:='Select ';
for i:=0 to SL.Count-1 do begin
SQL:=SQL+SL;
end;
SQL:=SQL+' As CalResult';
exeSQL(ADOQuery1,SQL);//这是一个我自己的执行SQL语句的函数,你需要修改
S:=ADOQuery1.FieldByName('CalResult').AsString;
showmessage(S);
end;
 
user comobj;

function expression(const srule:string):
var
sc : OleVariant;
begin
sc := CreateOleObject('MSScriptControl.ScriptControl.1');
sc.Language :='JavaScript';
result:=VarToStr(sc.Eval(srule));
end;
...
s:='1+2*3';
i:=expression(s);
 
这时一个简单的脚本解释程序,虽然是简单脚本解释,但也慢复杂的,我做这个用了1周才实现 任意的四则混合运算。
都给你吧 ,功能比你想要的多,我一个控件的一个属性
(语法错误时 GetBaseValue 返回 -2147483640)
:支持+ - × ÷ 四则混合运算,支持多级括号,支持相连运算10&20 --->1020
还支持以下函数
DayOfTheYear :今年第几天
DayOfTheMonth :本月第几天
DayOfTheWeek :本周第几天
MonthOfTheYear :今年第几月
WeekOfTheYear :今年第几周
WeekOfTheMonth :本月第几周
HourOfTheYear :今年第几小时
HourOfTheMonth :本月第几小时
HourOfTheWeek :本周第几小时
HourOfTheDay :本日第几小时
MinuteOfTheYear :本年第几分钟
MinuteOfTheMonth:本月第分钟
MinuteOfTheWeek :本周第几分钟
MinuteOfTheDay :本日第几分钟
MinuteOfTheHour :本小时第几分钟


function GetdispartChar(str:string;disPartset:chset;Var ch:char;var PartSt:string):integer;
var
i,j,len,dispos:integer;
ArrayChar:array of char;
begin
len:=0;
//---初始化分隔符-------
for i:=0 to 255 do
if char(i) in disPartSet then
begin
inc(len);
setlength(ArrayChar,len);
ArrayChar[len-1]:=char(i);
end;
//-------找出第一个分隔符所在位置-----
dispos:=2147483647;
for i:=0 to len-1 do
begin
j:=pos(ArrayChar,str);
if (J<>0) and (j<dispos) then
begin
dispos:=j;
ch:=ArrayChar;
end;
end;//end for i:=0 to len-1
if dispos=1 then PartSt:=''
else PartSt:=copy(str,1,dispos-1);
result:=dispos;
end;

function TBskyADODataSet.GetSubBaseValue(SBst:string):integer;
var
st:string;
begin
st:=sBst;
delallSpace(st);
//DelEndSpace(st);
// DelFirstSpace(st);
if st='' then result:=0
else if SearchErrorChar(st,['0'..'9'])=0 then
begin
result:=strtoint(st);
end
else if UpperCase(st)=UpperCase('DayOfTheYear') then
result:=DayOfTheYear(Now())
else if UpperCase(st)=UpperCase('DayOfTheMonth') then
result:=DayOfTheMonth(Now())
else if UpperCase(st)=UpperCase('DayOfTheWeek') then
result:=DayOfTheWeek(Now())
else if UpperCase(st)=UpperCase('MonthOfTheYear') then
result:=MonthOfTheYear(Now())
else if UpperCase(st)=UpperCase('WeekOfTheYear') then
result:=WeekOfTheYear(Now())
else if UpperCase(st)=UpperCase('WeekOfTheMonth') then
result:=WeekOfTheMonth(Now())
else if UpperCase(st)=UpperCase('HourOfTheYear') then
result:=HourOfTheYear(Now())
else if UpperCase(st)=UpperCase('HourOfTheMonth') then
result:=HourOfTheMonth(Now())
else if UpperCase(st)=UpperCase('HourOfTheWeek') then
result:=HourOfTheWeek(Now())
else if UpperCase(st)=UpperCase('HourOfTheDay') then
result:=HourOfTheDay(Now())
else if UpperCase(st)=UpperCase('MinuteOfTheYear') then
result:=MinuteOfTheYear(Now())
else if UpperCase(st)=UpperCase('MinuteOfTheMonth') then
result:=MinuteOfTheMonth(Now())
else if UpperCase(st)=UpperCase('MinuteOfTheWeek') then
result:=HourOfTheDay(Now())
else if UpperCase(st)=UpperCase('MinuteOfTheDay') then
result:=MinuteOfTheDay(Now())
else if UpperCase(st)=UpperCase('MinuteOfTheHour') then
result:=MinuteOfTheHour(Now())
else result:=-2147483640;
end;
function TBskyADODataSet.GetBaseValue(var Bst:string; pre:boolean):integer;
var
SdisChar:set of char;
preChar,dischar,MPrechar:char;
i,Int_haver,nownum,tempInt:integer;
partST:string;
ifDIgui:boolean;
begin
SdisChar:=['+','-','*','/','&','(',')'];
Int_haver:=0;
nownum:=0;
preChar:='b';
MPrechar:='s';
ifDIgui:=false;
DelENDChar(bst,'+');
Bst:=bst+'+';
if (pos('+-',Bst)<>0)
or (pos('++',Bst)<>0)
or (pos('+&',Bst)<>0)
or (pos('+*',Bst)<>0)
or (pos('+/',Bst)<>0)
or (pos('-+',Bst)<>0)
or (pos('--',Bst)<>0)
or (pos('-*',Bst)<>0)
or (pos('-/',Bst)<>0)
or (pos('-&',Bst)<>0)
or (pos('*+',Bst)<>0)
or (pos('*-',Bst)<>0)
or (pos('**',Bst)<>0)
or (pos('*/',Bst)<>0)
or (pos('*&',Bst)<>0)
or (pos('/+',Bst)<>0)
or (pos('/-',Bst)<>0)
or (pos('/*',Bst)<>0)
or (pos('//',Bst)<>0)
or (pos('/&',Bst)<>0)
or (pos('&+',Bst)<>0)
or (pos('&-',Bst)<>0)
or (pos('&*',Bst)<>0)
or (pos('&/',Bst)<>0)
or (pos('&&',Bst)<>0)
or (pos('(+',Bst)<>0)
or (pos('(-',Bst)<>0)
or (pos('(*',Bst)<>0)
or (pos('(/',Bst)<>0)
or (pos('(&',Bst)<>0)
or (pos('+)',Bst)<>0)
or (pos('-)',Bst)<>0)
or (pos('*)',Bst)<>0)
or (pos('/)',Bst)<>0)
or (pos('&)',Bst)<>0)
then
begin
result:=-2147483640;
exit;
end;

// dischar:='';
i:=GetdispartChar(Bst,Sdischar,dischar,partSt);
while i<>2147483647 do //有分隔符就一直运算
begin
System.Delete(Bst,1,i);
if (dischar='(') and (partSt<>'') then
begin
result:=-2147483640;
exit;
end;
//----------- + - * /------------
if dischar in ['+','-','&',')'] then
begin
tempInt:=GetSubBaseValue(partSt);
if tempInt=-2147483640 then
begin
result:=-2147483640;
exit;
end;
case mpreChar of
's': begin
if partSt='' then
begin
result:=-2147483640;
exit;
end;
nownum:=tempInt;
end;
'*': begin
nownum:=nownum*tempInt;
end;
'/':begin
if tempInt=0 then
begin
messagedlg('表达式除数为零!',mtError,[mbOK],0);
result:=-2147483640;
exit;
end;
nownum:=round(nownum/tempInt);
end;
end;//end case mpreChar
case preChar of
'b': begin
if (partSt='') then
begin
result:=-2147483640;
exit;
end;
Int_haver:=nownum;
end ;//'b'
'+': begin
Int_haver:=Int_haver+nownum;
end;
'-': begin
Int_haver:=Int_haver-nownum;
end;
'&': begin
Int_haver:=strtoint(inttostr(Int_haver)+inttostr(nownum));
end;
end;//end case
preChar:=dischar;
MpreChar:='s';
nownum:=0;
if (dischar=')') and pre then //递归返回
begin
result:=Int_haver;
exit;
end
else if (dischar=')') and (not pre) then
begin
result:=-2147483640;
exit;
end; //end 递归返回
end // if dischar in ['+','-','&']
else if dischar in ['*','/','('] then
begin
if dischar='(' then
begin
// pre:=true;
tempInt:=GetBaseValue(Bst,true);
if tempInt=-2147483640 then
begin
result:=-2147483640;
exit;
end;
ifDIgui:=true;
end
else
begin
tempInt:=GetSubBaseValue(partSt);
if tempInt=-2147483640 then
begin
result:=-2147483640;
exit;
end;
end;
case MpreChar of
's': begin
nownum:=tempInt;
end;
'*':begin
nownum:=nownum*tempInt;
end ;
'/':begin
if tempInt=0 then
begin
messagedlg('表达式除数为零!',mtError,[mbOK],0);
result:=-2147483640;
exit;
end;
nownum:=round(nownum/tempInt);
end;
end;//end case
if dischar<>'(' then MpreChar:=dischar;
end;// if dischar in ['*','/','(']
if ifDIgui then
begin
i:=GetdispartChar(Bst,Sdischar,dischar,partSt);
System.Delete(Bst,1,i);
if (partSt<>'') or (dischar='(')then
begin
result:=-2147483640;
exit;
end;
if dischar in ['*','/'] then MpreChar:=dischar
else
begin
case preChar of
'b': begin
//if (partSt='') then
// begin
// result:=-2147483640;
// exit;
// end;
Int_haver:=nownum;
end ;//'b'
'+': begin
Int_haver:=Int_haver+nownum;
end;
'-': begin
Int_haver:=Int_haver-nownum;
end;
'&': begin
Int_haver:=strtoint(inttostr(Int_haver)+inttostr(nownum));
end;
end;//end case
if (dischar=')') and pre then //递归返回
begin
result:=Int_haver;
exit;
end
else if (dischar=')') and (not pre) then
begin
result:=-2147483640;
exit;
end; //end 递归返回
preChar:=dischar;
MpreChar:='s';
nownum:=0;
end;//['+','-','&']
ifDIgui:=false;
end; //end ifDIgui
i:=GetdispartChar(Bst,Sdischar,dischar,partSt);
end; //end while
result:=Int_haver;
end;
 
对了上面的函数得到的都是整数,那是因为这是给我的TbskyADOSet 的baseValue用的,这个属性是自动产生 表的编号类字段值用的,比如一年中第几天作为 每天的基础编号xxx 然当天产生的记录编号在此基础上递增。
 
感谢各位的大力支持,我的问题已经搞定,多谢了!![:)][:)]
 
多人接受答案了。
 
后退
顶部