Delphi					분류
				
						델파이 eval 함수 비슷하게 구현
컨텐츠 정보
- 34,288 조회
- 0 추천
- 목록
본문
{
 You asked for something simple. But to evaluate an expression it's not that simple 'cause
 it envolves parsing a string and deal with all those tokens within an expression.
 // 
 Now. It's done. It is that simple..
 //
 Label.Caption := IntToStr( Eval( '(10   -2) + 50   (3+5)' ));
 //
 As you see this code supports parenteses and negative numbers.
 //
}
//>>>>
// This a support unit...
unit Stack;
INTERFACE
Uses Windows, Classes;
Const
  // This is more than enough for an expression.
  MaxStackSize = 1023;
Type
  TStack  =  class( TObject )
  private
     items : Array[0..MaxStackSize] of Integer;
     StkPtr : Integer;
  public
     procedure Reset;
     procedure AddItem( Item : Integer );
     function GetItem : Integer;
     function StackSize : Integer;
     function TestItem : Integer;
  end;
implementation
procedure TStack.Reset;
 StkPtr := MaxStackSize;
end;
procedure TStack.AddItem( Item : Integer );
begin
 Items[ StkPtr ] := Item;
 Dec( StkPtr );
end;
function TStack.GetItem : Integer;
begin
 Inc( StkPtr );
 GetItem := Items[ StkPtr ];
end;
function TStack.TestItem : Integer;
begin
 TestItem := Items[ StkPtr + 1 ];
end;
function TStack.StackSize : Integer;
begin
 StackSize := MaxStackSize - StkPtr;
end;
end.
// eof support unit
//>>>
//>>>
//  This is the main program...
// There is a label and a button on this form..
//
unit EvalUnit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Stack,
 StdCtrls;
Const
  Number = 0;
  TokError = 1;
  Plus = 2;
  Minus = 3;
  Times = 4;
  Divide = 5;
  LParen = 6;
  RParen = 7;
type
 TForm1 = class(TForm)
   Label1: TLabel;
   Button1: TButton;
   procedure FormDestroy(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
    Expression  : String;
    i, Code     : Integer;
    TokenPos    : Integer;
    Token       : String;
    TokenType   : Integer;
    MinusFlag   : Boolean;
    Arg1,Arg2   : Integer;
    procedure GetToken;
    function Eval( ExpressionToEvaluate : String ) : Integer;
 public
    Numbers     : TStack;
    Operators   : TStack;
 end;
var
 Form1: TForm1;
implementation
{$R  .DFM}
{Get the token the expression string}
procedure TForm1.GetToken;
begin
 {Clear the token string }
 Token := '';
 { if the expression has a digit, it's a number }
 if ( Ord( Expression[TokenPos]) >= Ord('0'))
     AND ( Ord( Expression[TokenPos] ) <= Ord('9')) then
  begin
       { Keep getting digits }
       repeat
          Token := Token + Expression[TokenPos];
          Inc(TokenPos);
       until ( Ord(Expression[TokenPos] ) < Ord('0'))
               or ( Ord(Expression[TokenPos] ) > Ord('9'))
               or ( TokenPos > Length( Expression ));
       { Mark the token Type as a Number }
       TokenType := Number;
     end
     { See if it's a plus sign }
     else if Expression[ TokenPos ] = '+' then
     begin
       TokenType := Plus;
       Inc( TokenPos );
     end
     { See if it's minus sign }
     else if Expression[ TokenPos ] = '-' then
     begin
       TokenType := Minus;
       Inc( TokenPos );
     end
     { See if it's a multiply sign }
     else if Expression[ TokenPos ] = ' ' then
     begin
       TokenType := Times;
       Inc( TokenPos );
     end
     { See if it's a divide sign }
     else if Expression[ TokenPos ] = '/' then
     begin
       TokenType := Times;
       Inc( TokenPos );
     end
     { See if it's a left parent sign }
     else if Expression[ TokenPos ] = '(' then
     begin
       TokenType := LParen;
       Inc( TokenPos );
     end
     { See if it's a right parent sign }
     else if Expression[ TokenPos ] = ')' then
     begin
       TokenType := RParen;
       Inc( TokenPos );
     end
     { None of that. So it's a junk }
     else
        TokenType := TokError;
end;
Function StripOff( ch : char; Str : String ) : String;
Var
 posi : byte;
begin
 posi := Pos( ch, str );
 while posi <> 0 do
 begin
   posi := Pos( ch, str );
   delete( str, posi, 1 );
 end;
 Result := str;
end;
function TForm1.Eval( ExpressionToEvaluate : String ) : Integer;
begin
  { Initialize the number and operator stacks }
  TokenPos := 1;
  { Make sure is something at the operators stack }
  Operators.AddItem( LParen );
  { Set the stack pointer }
  Numbers.Reset;
  Operators.Reset;
  { Strip all the spaces off } 
  Expression := StripOff(' ', ExpressionToEvaluate );
  while TokenPos <= Length( Expression ) do
  begin
     GetToken;
     While TokenType = LParen do
     begin
       Operators.AddItem( LParen );
       GetToken;
     end;
     { Check for negative number }
     if TokenType = Minus then
     begin
        MinusFlag := true;
        GetToken;
     end
     else
        MinusFlag := false;
     if TokenType = Number then
     begin
       Val( Token, i, code );
       if MinusFlag then
          i := -i;
       Numbers.AddItem( i );
       { See if at the end of the expression }
       if TokenPos <= Length( Expression ) then
       begin
         { Get the operators }
         repeat
            GetToken;
            if Operators.TestItem <>  LParen then
               { Do operations of higher precedence up to the left paren }
               while ( Operators.TestItem <> LParen ) and
                       ((( Operators.TestItem DIV 2 ) >= ( TokenType DIV 2 ))
                       or ( TokenType = RParen )) do
                       begin
                         Arg1 := Numbers.GetItem;
                         Arg2 := Numbers.GetItem;
                         case Operators.GetItem of
                              Plus   : Numbers.AddItem( Arg2 + Arg1 );
                              Minus  : Numbers.AddItem( Arg2 - Arg1 );
                              Times  : Numbers.AddItem( Arg2   Arg1 );
                              Divide : Numbers.AddItem( Arg2 DIV Arg1 );
                         end;
                       end;
                       if TokenType = RParen then
                          i := Operators.GetItem;
         until ( TokenType <> RParen )
                 or ( TokenPos >= Length( Expression ));
         Operators.AddItem( TokenType );
         end;
         end
         else
            TokenType := TokError;
         if Tokentype = TokError then
         begin
            TokenPos := Length( Expression ) + 1;
            Numbers.AddItem( 0 );
         end;
      end;
      while Operators.StackSize > 1 do
      begin
        Arg1 := Numbers.GetItem;
        Arg2 := Numbers.GetItem;
        repeat
           i := Operators.GetItem;
        until ( i <> LParen ) and ( i <> RParen );
        case i of
           Plus   : Numbers.AddItem( Arg2 + Arg1 );
           Minus  : Numbers.AddItem( Arg2 - Arg1 );
           Times  : Numbers.AddItem( Arg2   Arg1 );
           Divide : Numbers.AddItem( Arg2 DIV Arg1 );
       end;
    end;
    Result := Numbers.GetItem;
end;
// Link this to FormDestroy method..
procedure TForm1.FormDestroy(Sender: TObject);
begin
    Numbers.Free;
    Operators.Free;
end;
// Link this to FormCreate method..
procedure TForm1.FormCreate(Sender: TObject);
begin
    Numbers := TStack.Create;
    Operators := TStack.Create;
end;
// And this to Button1Click...
procedure TForm1.Button1Click(Sender: TObject);
begin
    Label1.Caption := IntToStr( Eval( '(10   -2) + 50   (3+5)' ));
end;
end.
( 
 There it is... Hope it helps.
 Reginaldo Ap. Rigo
 São Paulo, SP Brazil
 virtual@alphanet.com.br
 )
			관련자료
- 
			링크
			댓글 0
					
			
				등록된 댓글이 없습니다.
			
					 
								