Oppure

Loading
17/10/09 8:47
lorenzo
Ragazzi, da due giorni sto impazzendo su un pezzo di codice e non capisco cosa non va...allora si tratta di una classe incaricata di trasformare una stringa del tipo "3+2*4" nel suo reale valore calcolato(11 quindi)

ecco il codice:

unit Unit5; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, contnrs, Math, Dialogs;

type

  PInt = ^Integer;
  { RPNCreator }

  RPNCreator = class
  private
    operatori: TStack;
    operandi: TStack;
    value: String;
    function IsOperator(c: Char): Boolean;
    function Precedence(n1, n2: Char): Integer;
    procedure ReduceOperator;
    function InfixToPostfix: Double;
  public
    constructor Create(v: String);
    function Calculate: Double;
  end;

implementation

{ RPNCreator }

constructor RPNCreator.Create(v: String);
begin
  operatori := TStack.Create;
  operandi := Tstack.Create;
  value := v;    //la stringa che contiene la funzione da calcolare
end;

function RPNCreator.Calculate: Double;
begin
  Result := InfixToPostfix;
end;

function RPNCreator.IsOperator(c: Char): Boolean;
begin
  case c of
  '+', '-', '*', '/', '^': Result := True;
  else
    Result := False;
  end;
end;

function RPNCreator.Precedence(n1, n2: Char): Integer;
var
  a, b: Integer;
begin
  case n1 of
    '(': a := 4;
    '^': a := 3;
    '*', '/': a := 2;
    '+', '-': a := 1;
    else
      a := 0;
  end;

  case n2 of
    '(': b := 4;
    '^': b := 3;
    '*', '/': b := 2;
    '+', '-': b := 1;
    else
      b := 0;
  end;

  Result := a - b;
end;

procedure RPNCreator.ReduceOperator;
var
  opCurr: Char;
  a, b: Double;
  ris: PDouble;
begin
  opCurr := Char(operatori.Pop^);
  case opCurr of
    '*':
    begin
      a := Double(operandi.Pop^);
      b := Double(operandi.Pop^);
      New(ris);
      ris^ := a * b;
      operandi.Push(ris);
    end;
    '/':
    begin
      a := Double(operandi.Pop^);
      b := Double(operandi.Pop^);
      New(ris);
      ris^ := a / b;
      operandi.Push(ris);
    end;
    '+':
    begin
      a := Double(operandi.Pop^);
      b := Double(operandi.Pop^);
      New(ris);
      ris^ := a + b;
      operandi.Push(ris);
    end;
    '-':
    begin
      a := Double(operandi.Pop^);
      b := Double(operandi.Pop^);
      New(ris);
      ris^ := a - b;
      operandi.Push(ris);
    end;
    '^':
    begin
      a := Double(operandi.Pop^);
      b := Double(operandi.Pop^);
      New(ris);
      ris^ := Power(a, b);
      operandi.Push(ris);
    end;
  end;
end;

function RPNCreator.InfixToPostfix: Double;
var
  i, aux: Integer;
  c, s: Char;
  n: PInt;
begin
  i := 1;
  value := Trim(value);
  while i < Length(value) do
  begin
    if value[i] = ')' then
    begin
      while Char(operatori.Peek^) <> '(' do
      begin
        ReduceOperator;
      end;
      operatori.Pop;
    end;
    if value[i] = '(' then
      operatori.Push(@value[i])
    else
      if IsOperator(value[i]) then
      begin
        if Precedence(Char(operatori.Peek^), value[i]) < 0 then
          operatori.Push(@value[i])
        else
        begin
          ReduceOperator;
          operatori.Push(@value[i]);
        end;
      end
      else //è un numero, vediamo se è a più cifre
      begin
        New(n);
        n^ := 0;
        while TryStrToInt(value[i], aux) do
        begin
          n^ := n^ * 10;
          n^ := n^ + aux;
          Inc(i);
        end;
        operandi.Push(n);
      end;
      Inc(i);
  end;
  while operatori.Count > 0 do
    ReduceOperator;
  Result := Double(operandi.Peek^);
end;

end.    


è ancora un inizio e non è completo ma la parte che non funziona è la gestione dei numeri(vedi commento).
Allora, l'algoritmo termina correttamente e nella variabile puntatore "n" che poi inserisco nello stack ci trovo il valore corretto. Il problema è che quando faccio la Peek(o la Pop, è uguale) per ritornare il valore, mi trovo come risultato 2.4234364736e-34 cioè un numero a caso.

Perché questo???

ps: non è Delphi ma lazarus, comunque è lo stesso:k:
aaa
19/10/09 18:36
lorenzo
c'é nessunooooo? :D
aaa