Einzelnen Beitrag anzeigen

SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#19

Re: Automaten in Source Code

  Alt 21. Nov 2009, 16:23
So Leute, ich hab mal die "reine imperative" und die tabellengesteuerte Variante implementiert (haben beide auf Anhieb funktioniert )

Achso: die Automaten lesen eine Kommazahl und ersetzten das "," zu "-".

Delphi-Quellcode:
unit Imperative;

interface

type
  state = (sStart, sFrac, sTrunc, sStop);

type
  DEA_imperative = class
    private
      fInput,
      fOutput: string;
      fPos: BYTE;
      fState: state;
    public
      constructor _create(const input: string);
      destructor _destroy;

      procedure _execute;

      function _getOutput: string;
    end;

implementation

constructor DEA_imperative._create(const input: string);
begin
fInput := input + #0
end;

destructor DEA_imperative._destroy;
begin

end;

procedure DEA_imperative._execute;
begin
fPos := 1;
fState := sStart;
fOutput := '';

while fState <> sStop do begin
    case fState of
    sStart:
        case fInput[fPos] of
        '1'..'9': begin
          fOutput := fInput[fPos];

          fState := sTrunc
          end
        else fState := sStop
        end;
    sTrunc:
        case fInput[fPos] of
        '1'..'9': fOutput := fOutput + fInput[fPos];
        ',': begin
          fOutput := fOutput + '-';

          fState := sFrac
          end
        else fState := sStop
        end;
    sFrac:
        case fInput[fPos] of
        '1'..'9': fOutput := fOutput + fInput[fPos];
        else fState := sStop
        end
    end;

  fPos := fPos + 1
  end
end;

function DEA_imperative._getOutput: string;
begin
_getOutput := fOutput
end;

end.
Delphi-Quellcode:
unit TableControlled;

interface

type
  state = (sStart, sTrunc, sTruncToFrac, sFrac, sStop);

type
  DEA_tablecontrolled = class
    private
      fTable: array[sStart..sFrac] of array[CHAR] of state;
      fInput,
      fOutput: string;
      fPos: BYTE;
      fState: state;
    public
      constructor _create(const input: string);
      destructor _destroy;

      procedure _execute;

      function _getOutput: string;
    end;

implementation

constructor DEA_tablecontrolled._create(const input: string);
var
  i: CHAR;
begin
fInput := input + #0;

for i := #0 to #225 do begin
  fTable[sStart][i] := sStop;
  fTable[sTrunc][i] := sStop;
  fTable[sTruncToFrac][i] := sStop;
  fTable[sFrac][i] := sStop
  end;

fTable[sStart]['0'] := sTrunc; //KANN MAN DIE TABELLE "SCHÖNER" FÜLLEN?
fTable[sStart]['1'] := sTrunc;
fTable[sStart]['2'] := sTrunc;
fTable[sStart]['3'] := sTrunc;
fTable[sStart]['4'] := sTrunc;
fTable[sStart]['5'] := sTrunc;
fTable[sStart]['6'] := sTrunc;
fTable[sStart]['7'] := sTrunc;
fTable[sStart]['8'] := sTrunc;
fTable[sStart]['9'] := sTrunc;

fTable[sTrunc]['0'] := sTrunc;
fTable[sTrunc]['1'] := sTrunc;
fTable[sTrunc]['2'] := sTrunc;
fTable[sTrunc]['3'] := sTrunc;
fTable[sTrunc]['4'] := sTrunc;
fTable[sTrunc]['5'] := sTrunc;
fTable[sTrunc]['6'] := sTrunc;
fTable[sTrunc]['7'] := sTrunc;
fTable[sTrunc]['8'] := sTrunc;
fTable[sTrunc]['9'] := sTrunc;

fTable[sTrunc][','] := sTruncToFrac;

fTable[sTruncToFrac]['0'] := sFrac;
fTable[sTruncToFrac]['1'] := sFrac;
fTable[sTruncToFrac]['2'] := sFrac;
fTable[sTruncToFrac]['3'] := sFrac;
fTable[sTruncToFrac]['4'] := sFrac;
fTable[sTruncToFrac]['5'] := sFrac;
fTable[sTruncToFrac]['6'] := sFrac;
fTable[sTruncToFrac]['7'] := sFrac;
fTable[sTruncToFrac]['8'] := sFrac;
fTable[sTruncToFrac]['9'] := sFrac;

fTable[sFrac]['0'] := sFrac;
fTable[sFrac]['1'] := sFrac;
fTable[sFrac]['2'] := sFrac;
fTable[sFrac]['3'] := sFrac;
fTable[sFrac]['4'] := sFrac;
fTable[sFrac]['5'] := sFrac;
fTable[sFrac]['6'] := sFrac;
fTable[sFrac]['7'] := sFrac;
fTable[sFrac]['8'] := sFrac;
fTable[sFrac]['9'] := sFrac
end;

destructor DEA_tablecontrolled._destroy;
begin

end;

procedure DEA_tablecontrolled._execute;
begin
fPos := 1;
fState := sStart;
fOutput := '';

while fState <> sStop do begin
  fState := fTable[fState][fInput[fPos]];

    case fState of //ich habe es mir gespart, die einzelnen Routinen in die Tabelle zu übernehmen
    sTrunc: fOutput := fOutput + fInput[fPos];
    sTruncToFrac: fOutput := fOutput + '-';
    sFrac: fOutput := fOutput + fInput[fPos]
    end;

  fPos := fPos + 1
  end
end;

function DEA_tablecontrolled._getOutput: string;
begin
_getOutput := fOutput
end;

end.
Fazit:
mit der Case-Variante beschreibt man die Zustandsaktion UND die Übergänge!
=> Weniger Zustände.

=> Meine Meinung: Case-Var. (in DIESEM Beispiel) besser.


Zur OOP-Variante hab ich eine Frage:
Nicht dass ich nicht mit Klassen, Vererbung, etc. umgehen kann, ich bring mir grad selbst die Konzepte bei (Probleme lösen mittels OOP)

Wie erzeugt man am besten die Zustände?
Im Beispiel steht:
State := CoStartState.Create; erzeugt der StartZustand automatisch den "NextState" und das geht rekursiv immer so weiter bis StopZustand?

Ist das die "gute" OOP-Lösung?
Ich finde diese unübersichtlich und fehleranfällig.

Wie hat die OOP-Fraktion dieses Problem gelöst?
Sebastian
  Mit Zitat antworten Zitat