![]() |
#2
shuang2009112009-11-15 19:32
{*************************************************************************
1、只支持乘除加减、小括号,如:9/3+(89-3*2+(54-42)/3)。 2、也许会存在一些BUG,请各位大虾修正 **************************************************************************} unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, StrUtils; type TDirection = (dcForward, dcBack); TForm1 = class(TForm) edtExpression: TEdit; edtResult: TEdit; btnCalculate: TButton; procedure btnCalculateClick(Sender: TObject); private function GetExpression(var StartPos, EndPos: Integer; AExpression: string): string; function Calculate(AExpression: string): string; function CalculateEx(FirstNum, SecondNum, ASign: string): string; function GetLastSignPos(ASign, AExpression: string): Integer; function GetLatestSignPos(StartPos: Integer; AExpression: string): Integer; function GetNumber(var ResultPos: Integer;AExpression: string; Position: Integer; Direction: TDirection): string; function CalculateAll(AExpression: string): string; procedure CorrectExpression(var AExpression: string); function IsANegative(AExpression: string): Boolean; { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.btnCalculateClick(Sender: TObject); begin edtResult.Text := CalculateAll(edtExpression.Text); end; function TForm1.Calculate(AExpression: string): string; var Pos1: Integer; {符号*位置} Pos2: Integer; {符号/位置} Pos3: Integer; {符号+位置} Pos4: Integer; {符号-位置} FirstNum, SecondNum, ResultNum: string; //第一个数值,第二个数值,计算结果值 StartPos, EndPos: Integer; //二元表达式的开始位置、结束位置 FNegative: Boolean; //负数 begin Result := ''; StartPos := -1; EndPos := -1; FNegative := False; CorrectExpression(AExpression); //表达式修正 while Length(AExpression) > 0 do begin CorrectExpression(AExpression); //表达式修正 Pos1 := Pos('*', AExpression); Pos2 := Pos('/', AExpression); Pos3 := Pos('+', AExpression); Pos4 := Pos('-', AExpression); if IsANegative(AExpression) then //为一个负数的时 begin Result := AExpression; Exit; end; if (Pos1 > 0) or (Pos2 > 0) then //有乘除先算乘除 begin if Pos1 > Pos2 then //乘号的位置在除号的后面, 按照从左至右的顺序, 先算除法 begin if Pos2 > 0 then //如果有除法 begin FirstNum := GetNumber(StartPos, AExpression, Pos2, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos2, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '/'); end else //没有除法就算乘法 begin FirstNum := GetNumber(StartPos, AExpression, Pos1, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos1, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '*'); end; end else //乘号的位置在除号的前面, 按照从左至右的顺序, 先算乘法 begin if Pos1 > 0 then //如果有乘法 begin FirstNum := GetNumber(StartPos, AExpression, Pos1, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos1, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '*'); end else //没有乘法就算除法 begin FirstNum := GetNumber(StartPos, AExpression, Pos2, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos2, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '/'); end; end; end else if (Pos3 > 0) or (Pos4 >0) then //没有乘除算加减 begin if Pos3 > Pos4 then //加号的位置在减号位置的后面, 按照从左至右的顺序, 先算减法 begin if Pos4 > 1 then //如果有减法 begin FirstNum := GetNumber(StartPos, AExpression, Pos4, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos4, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '-'); end else //没有减法就算加法 begin FirstNum := GetNumber(StartPos, AExpression, Pos3, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos3, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '+'); end; end else //加号的位置在减号位置的前面, 按照从左至右的顺序, 先算加法 begin if Pos3 > 0 then //如果有加法 begin FirstNum := GetNumber(StartPos, AExpression, Pos3, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos3, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '+'); end else //没有加法算减法 begin if Pos4 = 1 then //减号在最前面,如-7-19 begin AExpression := Copy(AExpression, 2, MaxInt); FNegative := True; Continue; end; if FNegative then begin AExpression := Format('-%s', [AExpression]); Inc(Pos4); FNegative := False; end; FirstNum := GetNumber(StartPos, AExpression, Pos4, dcBack); SecondNum := GetNumber(EndPos, AExpression, Pos4, dcForward); ResultNum := CalculateEx(FirstNum, SecondNum, '-'); end; end; end else //没有乘除加减法即退出 Break; AExpression := Format('%s%s%s', [Copy(AExpression, 1, StartPos - 1), ResultNum, Copy(AExpression, EndPos + 1, MaxInt)]); end; Result := AExpression; end; function TForm1.CalculateAll(AExpression: string): string; var StartPos, EndPos: Integer; //子表达式的开始位置/结束位置 SubExpression: string; //子表达式 ResultValue: string; //计算结果 begin while Length(AExpression) > 0 do begin SubExpression := GetExpression(StartPos, EndPos, AExpression); ResultValue := Calculate(SubExpression); AExpression := Format('%s%s%s', [Copy(AExpression, 1, StartPos - 1), ResultValue, Copy(AExpression, EndPos + 1, MaxInt)]); if (Pos('*', AExpression) = 0) and (Pos('/', AExpression) = 0) and (Pos('+', AExpression) = 0) and (Pos('-', AExpression) = 0) then Break; //一个正数时 if (Pos('*', AExpression) = 0) and (Pos('/', AExpression) = 0) and (Pos('+', AExpression) = 0) and (Pos('-', AExpression) = 1) then Break; //一个负数时 end; Result := AExpression; end; function TForm1.CalculateEx(FirstNum, SecondNum, ASign: string): string; var fFirstNum, fSecondNum: Double; begin Result := ''; fFirstNum := StrToFloat(FirstNum); fSecondNum := StrToFloat(SecondNum); if ASign = '+' then Result := FloatToStr(fFirstNum + fSecondNum); if ASign = '-' then Result := FloatToStr(fFirstNum - fSecondNum); if ASign = '*' then Result := FloatToStr(fFirstNum * fSecondNum); if ASign = '/' then Result := FloatToStr(fFirstNum / fSecondNum); end; {取括号内表达式} function TForm1.GetExpression(var StartPos, EndPos: Integer; AExpression: string): string; begin if Pos('(', AExpression) > 0 then begin StartPos := GetLastSignPos('(', AExpression); EndPos := GetLatestSignPos(StartPos, AExpression); Result := Copy(AExpression, StartPos + 1, EndPos - StartPos - 1); end else begin StartPos := 1; EndPos := Length(AExpression); Result := AExpression; end; end; function TForm1.GetLatestSignPos(StartPos: Integer; AExpression: string): Integer; var iCount: Integer; sLenght: Integer; //字符串长度 AExpr: string[250]; begin Result := -1; AExpr := AExpression; sLenght := Ord(AExpr[0]); for iCount := StartPos to sLenght do begin if AExpr[iCount] = ')' then begin Result := iCount; Break; end; end; end; {取特定字符在表达式里的最后出现的位置} function TForm1.GetLastSignPos(ASign, AExpression: string): Integer; var iCount: Integer; sLenght: Integer; //字符串长度 AExpr: string[250]; begin Result := -1; AExpr := AExpression; sLenght := Ord(AExpr[0]); for iCount := 1 to sLenght do begin if AExpr[iCount] = ASign then Result := iCount; end; end; {在一个字符串里,根据指定的位置,向前/后取一个数字} function TForm1.GetNumber(var ResultPos: Integer; AExpression: string; Position: Integer; Direction: TDirection): string; var AExpr: string[250]; iCount: Integer; AValue: string; SpecialPos: Integer; //特殊位置 begin AExpr := AExpression; iCount := Position; AValue := ''; case Direction of dcBack: begin Dec(iCount); while (iCount > 0) do begin if (iCount = 1) and (AExpr[iCount] = '-') then begin AValue := Format('%s%s', [AExpr[iCount], AValue]); ResultPos := iCount; Break; end; if (AExpr[iCount] = '+') or (AExpr[iCount] = '-') or (AExpr[iCount] = '*') or (AExpr[iCount] = '/') then Break; AValue := Format('%s%s', [AExpr[iCount], AValue]); ResultPos := iCount; Dec(iCount); end; end; dcForward: begin Inc(iCount); SpecialPos := iCount; while iCount <= Ord(AExpr[0]) do begin if (iCount = SpecialPos) and (AExpr[iCount] = '-') then //乘(除)后面跟一个负数时 begin AValue := Format('%s%s', [AValue, AExpr[iCount]]); ResultPos := iCount; Inc(iCount); Continue; end; if (AExpr[iCount] = '+') or (AExpr[iCount] = '-') or (AExpr[iCount] = '*') or (AExpr[iCount] = '/') then Break; AValue := Format('%s%s', [AValue, AExpr[iCount]]); ResultPos := iCount; Inc(iCount); end; end; end; Result := AValue; end; {表达式修正} procedure TForm1.CorrectExpression(var AExpression: string); begin AExpression := StringReplace(AExpression, '--', '+', []); //负负得正 AExpression := StringReplace(AExpression, '+-', '-', []); //加上一个负数等于减去该数绝对值 end; {判断一个表达式是否为一个负数} function TForm1.IsANegative(AExpression: string): Boolean; var OutVal: Double; begin Result := TryStrToFloat(AExpression, OutVal); Result := OutVal < 0; end; end. |
不同于简单的计算器程序,窗体上只有两个edit 一个用于输入 一个用于输出结果 和一个button,要求点击按钮就自动运算输入框中的混合运算。请教大侠们怎么实现呀?
[ 本帖最后由 超超小火星 于 2009-11-10 12:57 编辑 ]