16,748
社区成员
发帖
与我相关
我的任务
分享
{首先向楼上各位无私奉献的朋友学习了
然后我也写了一段, 只是提供一个思路, 通用性极不强, 楼主可以无视而过}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure Test(Str: string);
published
function MyFunc1(A, B: integer): integer;
function MyFunc2(A, B: integer): integer;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
function TForm1.MyFunc1(A, B: integer): integer;
begin
Result := A + B;
end;
function TForm1.MyFunc2(A, B: integer): integer;
begin
Result := A * B;
end;
procedure TForm1.Test(Str: string);
var
I, J: integer;
FuncName: string;
Var1, Var2: integer;
SS: TStringList;
pFunc: Pointer;
Rst: integer;
begin
Str := StringReplace(Str, #32, '', [rfReplaceAll]);
FuncName := Copy(Str, 1, Pos('(', Str)-1);
SS := TStringList.Create;
I := Pos('(', Str);
J := Pos(')', Str);
SS.Text := StringReplace(Copy(Str, I+1, J-I-1), ',', #10, [rfReplaceAll]);
try
Var1 := StrtoInt(SS[0]);
except
Var1 := PInteger(Self.FieldAddress(SS[0]))^;
end;
try
Var2 := StrtoInt(SS[1]);
except
Var2 := PInteger(Self.FieldAddress(SS[1]))^;
end;
pFunc := Self.MethodAddress(FuncName);
asm
mov eax, Self
mov edx, Var1
mov ecx, Var2
call [pFunc]
mov Rst, eax
end;
Showmessage(InttoStr(Rst));
SS.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Test('MyFunc1(55,44)');
Test('MyFunc2(3,5)');
end;
end.
function TCalculator.PushParam(const AParam: String): Boolean;
var
iLoop: Integer;
begin
Result := False;
for iLoop := Low(FParamArray) to High(FParamArray) do // Iterate
begin
// SameText is not Case Sensitive
if SameText(FParamArray[iLoop].Param, AParam) then
begin
Result := PushNumber(FParamArray[iLoop].Value);
Break;
end;
end; // end for
end;
procedure TCalculator.SetCalcExpression(const Value: String);
function StringReplaceEx(const S, OldPattern, NewPattern: string;
Flags: TReplaceFlags): string;
var
SearchStr, Patt, NewStr: string;
Offset: Integer;
begin
if rfIgnoreCase in Flags then
begin
SearchStr := UpperCase(S);
Patt := UpperCase(OldPattern);
end else
begin
SearchStr := S;
Patt := OldPattern;
end;
NewStr := S;
Result := '';
while SearchStr <> '' do
begin
Offset := Pos(Patt, SearchStr);
if Offset = 0 then
begin
Result := Result + NewStr;
Break;
end;
Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
if not (rfReplaceAll in Flags) then
begin
Result := Result + NewStr;
Break;
end;
SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
end;
end;
var
iLoop: TOperator;
PseudoCode: String;
Operator: String;
RFlag: TReplaceFlags;
begin
FCalcExpression := StringReplaceEx(Value, ' ', '', [rfReplaceAll]);
// 替换伪代码
RFlag := [rfReplaceAll, rfIgnoreCase];
for iLoop := Low(TOperator) to High(TOperator) do
begin
PseudoCode := Trim(Operators[iLoop].Pseudocode);
if Length(PseudoCode) <> 0 then
begin
Operator := Operators[iLoop].Operator;
FCalcExpression := StringReplaceEx(FCalcExpression, Pseudocode, Operator, RFlag);
end;
end;
end;
end.
function TCalculator.Calc(const Expression: String): Double;
begin
CalcExpression := Expression;
Result := Calc;
end;
function TCalculator.CalcBool: Boolean;
var
FR: Double;
begin
FR := Calc;
Result := not IsZero(FR, CONST_EPSILON);
end;
function TCalculator.CalcBool(const Expression: String): Boolean;
var
FR: Double;
begin
FR := Calc(Expression);
Result := not IsZero(FR, CONST_EPSILON);
end;
procedure TCalculator.ClearParam;
begin
SetLength(FParamArray, 0);
end;
constructor TCalculator.Create;
begin
ClearParam;
AddParam('INF', Infinity);
AddParam('PI', PI);
end;
destructor TCalculator.Destroy;
begin
ClearParam;
inherited;
end;
procedure TCalculator.DoCalc;
function CalcSingle(const AOperator: TOperator): Double; // 单目操作符
var
iLoop: Integer;
Base: Double;
begin
Result := 0.00;
Base := PopNumber;
case AOperator of // case
oNot:
Result := IfThen(IsZero(Base, CONST_EPSILON), 1, 0); //
oABS:
Result := Abs(Base);
oSqr:
Result := Sqr(Base);
oSqt:
Result := Sqrt(Abs(Base));
oLn:
Result := Ln(Base);
oFact:
begin
Result := Round(Base);
for iLoop := Round(Base) - 1 downto 1 do
try
Result := Result * iLoop;
except
Result := Infinity;
end;
end;
oSin:
Result := Sin(Base);
oCos:
Result := Cos(Base);
oTan:
Result := Tan(Base);
oCot:
Result := Cot(Base);
end; // end case
end;
function CalcDouble(const AOperator: TOperator): Double; // 双目操作符
var
Base, Exponent: Double;
begin
Result := 0.00;
Exponent := PopNumber;
Base := PopNumber;
case AOperator of // case
oPower, oPow:
Result := Power(Base, Exponent);
oMulitiple:
Result := Base * Exponent;
oDevide:
if SameValue(Exponent, 0) then
Result := Infinity
else Result := Base / Exponent;
oMod:
if SameValue(Round(Exponent), 0) then
Result := Infinity
else Result := Round(Base) mod Round(Exponent);
oAdd:
Result := Base + Exponent;
oSub:
Result := Base - Exponent;
oLog:
Result := LogN(Base, Exponent);
oLdexp:
Result := Ldexp(Base, Round(Exponent));
oGreater:
Result := IfThen(Base > Exponent, 1, 0);
oLess:
Result := IfThen(Base < Exponent, 1, 0);
oNoGreater:
Result := IfThen(Base <= Exponent, 1, 0);
oNoLess:
Result := IfThen(Base >= Exponent, 1, 0);
oEqual:
Result := IfThen((Base = Exponent) or SameValue(Base, Exponent, CONST_EPSILON), 1, 0);
oUnEqual:
Result := IfThen((Base = Exponent) or SameValue(Base, Exponent, CONST_EPSILON), 0, 1);
oAnd:
Result := IfThen((Base > CONST_EPSILON) and (Exponent > CONST_EPSILON), 1, 0);
oOr:
Result := IfThen((Base > CONST_EPSILON) or (Exponent > CONST_EPSILON), 1, 0);
end;
end;
var
Operator: TOperator;
FCalcResult: Double;
begin
Operator := PopOperator;
if not (Operator in [oBracketL, oBracketR]) then
begin
case Operators[Operator].OperandCount of // case
1: FCalcResult := CalcSingle(Operator);
2: FCalcResult := CalcDouble(Operator);
else FCalcResult := 0.00; // case else
end; // end case
PushNumber(FCalcResult); // 计算结果入栈
end;
end;
function TCalculator.GetOperatorType(const AChar: Char): TOperator;
var
iLoop: TOperator;
begin
Result := TOperator(-1);
for iLoop := Low(TOperator) to High(TOperator) do // Iterate
if AChar = Operators[iLoop].Operator then
begin
Result := iLoop;
Break;
end;
end;
procedure TCalculator.ParseChar(const AChar: Char);
function GetCalcCharState(const AChar: Char): TCalcState;
begin
Result := csParam;
if AChar in SetOfNumber then
Result := csNumber
else if GetOperatorType(AChar) in [Low(TOperator)..High(TOperator)] then
Result := csOperator;
end;
var
CalcCharState: TCalcState;
TempDouble: Double;
begin
CalcCharState := GetCalcCharState(AChar);
try
case CalcCharState of // case
csNumber, csParam:
FCalcString := FCalcString + AChar;
csOperator:
begin
case FCalcState of // case
csNumber:
if TryStrToFloat(FCalcString, TempDouble) then
PushNumber(TempDouble)
else raise Exception.Create('Invalid Number Input!');
csParam:
if not PushParam(FCalcString) then
raise Exception.Create('Invalid Parameter Input!');
end; // end case
FCalcString := '';
if not PushOperator(GetOperatorType(AChar)) then
raise Exception.Create('Invalid Operator Input!');
end;
end; // end case
finally
FCalcState := CalcCharState; // 保存当前字符类型
end;
end;
function TCalculator.PeekOperator: TOperator;
begin
Result := TOperator(FStackOperators.Peek);
end;
function TCalculator.PopNumber: Double;
begin
Result := Double(FStackNumbers.Pop);
end;
function TCalculator.PopOperator: TOperator;
begin
Result := TOperator(FStackOperators.Pop);
end;
function TCalculator.PushNumber(const ANumber: Double): Boolean;
begin
Result := FStackNumbers.Push(ANumber);
end;
function TCalculator.PushOperator(const AOperator: TOperator): Boolean;
function OperatorCanPush: Boolean;
var
oOperator: TOperator;
begin
Result := True;
if FStackOperators.Count > 0 then
begin
oOperator := PeekOperator; // 得到栈顶操作符
Result := (oOperator = oBracketL) or
(Operators[AOperator].Rights < Operators[oOperator].Rights);
end;
end;
begin
Result := True;
if AOperator <> oComma then
begin
{ 判断入栈操作符与栈顶操作符优先级 }
while not OperatorCanPush do
DoCalc;
if AOperator <> oBracketR then
Result := FStackOperators.Push(AOperator)
else begin
PopOperator;
Result := True;
end;
end;
end;