Her kommer den så
... 175 linjer kode
:
function CalculateResult(Exp: String; Validate: Boolean = True): Extended;
const
Decimal: Char = '.';
type
PPart = ^TPart;
TPart = record
Content: String;
Positive: Boolean;
Result: Extended;
end;
TParts = array of TPart;
var
I: Integer;
Parts: TParts;
function GetFloatingPoint(): String;
var
Dec: PChar;
begin
Dec := StrAlloc(10);
GetLocaleInfo(
LOCALE_SYSTEM_DEFAULT,
LOCALE_SDECIMAL,
Dec,
10);
Result := Dec;
end;
function SplitInParts(S: String): TParts;
var
I: Integer;
Tmp: String;
function StripSpaces(S: String): String;
var
I: Integer;
begin
I := Pos(' ', S);
while I > 0 do begin
Delete(S, I, 1);
I := Pos(' ', S);
end;
Result := S;
end;
begin
S := StripSpaces(S); // Vi fjerner lige mellemrum
// Her kommer tre grimme fixes :D
S := S + '+';
if (S[1] <> '+') and (S[1] <> '-') then
S := '+' + S;
Tmp := S[1];
for I := 2 to Length(S) do begin
if (S[I] <> '+') and (S[I] <> '-') then
Tmp := Tmp + S[I]
else begin
SetLength(Result, High(Result)+2);
Result[High(Result)].Content := Tmp;
case S[I] of
'+': Result[High(Result)].Positive := True;
'-': Result[High(Result)].Positive := False;
end;
Tmp := S[I];
end;
end;
end;
procedure CalculatePart(Part: PPart);
type
TSplitted = record
Content: String;
Action: Integer;
end;
var
I: Integer;
Splitted: array of TSplitted;
Tmp: String;
Tmp2: String;
TmpResult: Extended;
begin
Tmp := '';
// Grimt grimt fix!
Tmp2 := Part.Content + '*';
for I := 1 to Length(Tmp2) do begin
if (Tmp2[I] <> '*') and (Tmp2[I] <> '/') then
Tmp := Tmp + Tmp2[I]
else begin
SetLength(Splitted, High(Splitted)+2);
if (Tmp[1] <> '-') and (Tmp[1] <> '+') then
Tmp := '+' + Tmp;
Splitted[High(Splitted)].Content := Tmp;
case Tmp2[I] of
'*': Splitted[High(Splitted)].Action := 0;
'/': Splitted[High(Splitted)].Action := 1;
end;
Tmp := '';
end;
end;
// Vi har nu alt hvad vi skal bruge for at udregne resultatet :D
TmpResult := StrToFloat(Splitted[0].Content);
for I := 1 to High(Splitted) do begin
case Splitted[I-1].Action of
0: TmpResult := TmpResult * StrToFloat(Splitted[I].Content);
1: TmpResult := TmpResult / StrToFloat(Splitted[I].Content);
end;
end;
Part.Result := TmpResult;
end;
function FindClosingBracket(S: String; StartingBracket: Integer): Integer;
var
I: Integer;
Cur: Integer;
begin
Cur := 1;
for I := StartingBracket+1 to Length(S) do begin
if S[I] = '(' then
Inc(Cur)
else if S[I] = ')' then
Dec(Cur);
if Cur = 0 then begin
Result := I-StartingBracket+1;
Break;
end;
end;
end;
var
J: Integer;
begin
try
// Valider inputtet
if Validate then begin
for I := 1 to Length(Exp) do begin
if not (Exp[I] in ['0'..'9', '*', '/', '+', '-', '(', ')', Decimal]) then
raise Exception.Create('');
end;
Exp := StringReplace(Exp,
Decimal,
GetFloatingPoint,
[rfReplaceAll]+[rfIgnoreCase]);
Exp := StringReplace(Exp, '+-', '-', [rfReplaceAll]);
Exp := StringReplace(Exp, '--', '+', [rfReplaceAll]);
Exp := StringReplace(Exp, '-+', '-', [rfReplaceAll]);
Exp := StringReplace(Exp, '++', '+', [rfReplaceAll]);
end;
// "Smart" lille fix til at udregne parenteser :D
I := Pos('(', Exp);
while I <> 0 do begin
J := FindClosingBracket(Exp, I);
Exp := StringReplace(Exp,
Copy(Exp, I, J),
FloatToStr(CalculateResult(Copy(Exp, I+1, J-2), False)),
[rfReplaceAll]+[rfIgnoreCase]);
I := Pos('(', Exp);
end;
Parts := SplitInParts(Exp); // Først deler vi vores expression op
for I := 0 to High(Parts) do begin
CalculatePart(@Parts[I]);
end;
// Nu skal vi lige lave sidste udregning og så er vi færdige :D
Result := Parts[0].Result;
for I := 1 to High(Parts) do begin
case Parts[I].Positive of
True: Result := Result + Parts[I].Result;
False: Result := Result - Parts[I].Result;
end;
end;
except
on E: Exception do begin Result := NaN; end;
end;
end;
For at virke kræver det at SysUtils, Math og Windows unitsne er under "uses" sektionen. For at bruge parsen kan du gøre sådan her:
var
F: Extended;
Exp: String; // Dette er stringen med matematisk indhold
begin
Exp := '(65+98*4/(65))';
F := CalculateResult(Exp);
if not IsNaN(F) then
ShowMessage(FloatToStr(F))
else
ShowMessage('Det matematiske udtryk er ukorrekt!');
end;
EDIT: Glemte at skrive at decimal-seperatoren i inputtet SKAL være "." (Altså et punktum)
MH.
The-Freak
Livet er for kort til at kede sig.
[Redigeret d. 19/01-05 14:56:07 af The-Freak]