AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Parsen von Seitenzahlen

Ein Thema von Schwedenbitter · begonnen am 19. Jul 2009 · letzter Beitrag vom 18. Aug 2012
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#21

AW: Parsen von Seitenzahlen

  Alt 18. Aug 2012, 16:39
Wäre es nicht wesentlich schicker dieses mit dem State-Pattern zu lösen?
Schicker vielleicht, aber nicht unbedingt lesbarer und ein klein wenig Overkill.
Aber wesentlich angenehmer, wenn es um die Erweiterbarkeit geht.
Hier der Ansatz mit dem State-Pattern:
Delphi-Quellcode:
unit PageStrParser;

interface

{$DEFINE UseStateInstanceCache }

uses
  Classes
{$IFDEF UseStateInstanceCache}
    , Generics.Collections
{$ENDIF};

type
  TPageStrParser = class;
  TPageStrParserStateClass = class of TPageStrParserState;

  TPageStrParserState = class
  private
    FParser : TPageStrParser;
    procedure ChangeState( NewState : TPageStrParserStateClass );
    procedure AddCharToCurrPage1( Ch : Char );
    procedure AddCharToCurrPage2( Ch : Char );
    procedure AddCurrPagesToList;
  public
    constructor Create( AParser : TPageStrParser );

    procedure ProcessChar( Ch : Char; Pos : Integer ); virtual; abstract;
  end;

  TPageStrParser = class
  private
    FState : TPageStrParserState;
{$IFDEF UseStateInstanceCache}
    FStateCache : TDictionary<TPageStrParserStateClass, TPageStrParserState>;
{$ENDIF}
    FCurrPageFrom : string;
    FCurrPageTo : string;
    FPageList : TStrings;
    function GetState : TPageStrParserStateClass;
    procedure SetState( const Value : TPageStrParserStateClass );
  protected
    procedure AddCharToCurrPage1( Ch : Char );
    procedure AddCharToCurrPage2( Ch : Char );
    procedure AddCurrPagesToList;

    property State : TPageStrParserStateClass read GetState write SetState;
  public
    constructor Create;
    destructor Destroy; override;

    procedure ExtractPages( const s : string; const aPageList : TStrings );
  end;

implementation

uses
  SysUtils;

type
  TPageStrParserPageFromStartState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserPageFromState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserPageFromEndState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserPageToStartState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserPageToState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserPageToEndState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

  TPageStrParserErrorState = class( TPageStrParserState )
  public
    procedure ProcessChar( Ch : Char; Pos : Integer ); override;
  end;

resourcestring
  EParserError = 'Error in line at position %d: Invalid or Unexpected Char "%s"';

  { TPageStrParser }

procedure TPageStrParser.AddCharToCurrPage1( Ch : Char );
begin
  FCurrPageFrom := FCurrPageFrom + Ch;
end;

procedure TPageStrParser.AddCharToCurrPage2( Ch : Char );
begin
  FCurrPageTo := FCurrPageTo + Ch;
end;

procedure TPageStrParser.AddCurrPagesToList;
var
  lFrom, lTo : Integer;
  lPage : Integer;
  lPageNr : string;
begin
  lFrom := StrToInt( FCurrPageFrom );
  lTo := StrToIntDef( FCurrPageTo, lFrom );

  if lFrom <= lTo
  then
    for lPage := lFrom to lTo do
      begin
        lPageNr := IntToStr( lPage );
        FPageList.Add( lPageNr );
      end
  else
    for lPage := lFrom downto lTo do
      begin
        lPageNr := IntToStr( lPage );
        FPageList.Add( lPageNr );
      end;

  FCurrPageFrom := '';
  FCurrPageTo := '';
end;

constructor TPageStrParser.Create;
begin
  inherited;
{$IFDEF UseStateInstanceCache}
  FStateCache := TObjectDictionary<TPageStrParserStateClass, TPageStrParserState>.Create( [doOwnsValues] );
{$ENDIF}
end;

destructor TPageStrParser.Destroy;
begin
{$IFDEF UseStateInstanceCache}
  FStateCache.Free;
{$ELSE}
  FState.Free;
{$ENDIF}
  inherited;
end;

procedure TPageStrParser.ExtractPages( const s : string; const aPageList : TStrings );
var
  i : Integer;
  Ch : Char;
begin
  FPageList := aPageList;

  FPageList.BeginUpdate;
  try
    FPageList.Clear;

    State := TPageStrParserPageFromStartState;

    FCurrPageFrom := '';
    FCurrPageTo := '';

    for i := 1 to Length( s ) do
      begin
        Ch := s[i];
        FState.ProcessChar( Ch, i );

        if State = TPageStrParserErrorState
        then
          FState.ProcessChar( Ch, i );

      end;

    if FCurrPageFrom <> ''
    then
      AddCurrPagesToList;

  finally
    FPageList.EndUpdate;
  end;
end;

function TPageStrParser.GetState : TPageStrParserStateClass;
begin
  Result := TPageStrParserStateClass( FState.ClassType );
end;

procedure TPageStrParser.SetState( const Value : TPageStrParserStateClass );
begin
{$IFDEF UseStateInstanceCache}
  if FStateCache.ContainsKey( Value )
  then
    FState := FStateCache.Items[Value]
  else
    begin
      FState := Value.Create( Self );
      FStateCache.Add( Value, FState );
    end;
{$ELSE}
  FState.Free;
  FState := Value.Create( Self );
{$ENDIF}
end;

{ TPageStrParserState }

procedure TPageStrParserState.AddCharToCurrPage1( Ch : Char );
begin
  FParser.AddCharToCurrPage1( Ch );
end;

procedure TPageStrParserState.AddCharToCurrPage2( Ch : Char );
begin
  FParser.AddCharToCurrPage2( Ch );
end;

procedure TPageStrParserState.AddCurrPagesToList;
begin
  FParser.AddCurrPagesToList;
end;

procedure TPageStrParserState.ChangeState( NewState : TPageStrParserStateClass );
begin
  FParser.State := NewState;
end;

constructor TPageStrParserState.Create( AParser : TPageStrParser );
begin
  inherited Create;
  FParser := AParser;
end;

{ TPageStrParserErrorState }

procedure TPageStrParserErrorState.ProcessChar( Ch : Char; Pos : Integer );
begin
  raise Exception.Create( Format( EParserError, [Pos, Ch] ) );
end;

{ TPageStrParserPageFromStartState }

procedure TPageStrParserPageFromStartState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ;
    '0' .. '9' :
      begin
        AddCharToCurrPage1( Ch );
        ChangeState( TPageStrParserPageFromState );
      end;
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

{ TPageStrParserPageFromState }

procedure TPageStrParserPageFromState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ChangeState( TPageStrParserPageFromEndState );
    '0' .. '9' :
      begin
        AddCharToCurrPage1( Ch );
      end;
    '-' :
      begin
        ChangeState( TPageStrParserPageToStartState );
      end;
    ';', ',' :
      begin
        AddCurrPagesToList;
        ChangeState( TPageStrParserPageFromStartState );
      end;
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

{ TPageStrParserPageFromEndState }

procedure TPageStrParserPageFromEndState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ;
    '-' :
      ChangeState( TPageStrParserPageToStartState );
    ',', ';' :
      begin
        AddCurrPagesToList;
        ChangeState( TPageStrParserPageFromStartState );
      end
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

{ TPageStrParserPageToStartState }

procedure TPageStrParserPageToStartState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ;
    '0' .. '9' :
      begin
        AddCharToCurrPage2( Ch );
        ChangeState( TPageStrParserPageToState );
      end;
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

{ TPageStrParserPageToState }

procedure TPageStrParserPageToState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ChangeState( TPageStrParserPageToEndState );
    '0' .. '9' :
      begin
        AddCharToCurrPage2( Ch );
      end;
    ';', ',' :
      begin
        AddCurrPagesToList;
        ChangeState( TPageStrParserPageFromStartState );
      end;
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

{ TPageStrParserPageToEndState }

procedure TPageStrParserPageToEndState.ProcessChar( Ch : Char; Pos : Integer );
begin
  case Ch of
    ' ' :
      ;
    ',', ';' :
      begin
        AddCurrPagesToList;
        ChangeState( TPageStrParserPageFromStartState );
      end
  else
    ChangeState( TPageStrParserErrorState );
  end;
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#22

AW: Parsen von Seitenzahlen

  Alt 18. Aug 2012, 16:49


Und was willst Du erweitern? Lass uns doch mal checken, ob das wirklich erweiterbarer ist. Gib mal was vor?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#23

AW: Parsen von Seitenzahlen

  Alt 18. Aug 2012, 16:54


Und was willst Du erweitern? Lass uns doch mal checken, ob das wirklich erweiterbarer ist. Gib mal was vor?
Das weiß ich ja noch nicht, sonst wäre ich ja Hellseher, wenn ich wüßte, wie die Anforderung in x Tagen sich ändern
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#24

AW: Parsen von Seitenzahlen

  Alt 18. Aug 2012, 18:01
Na, ich wüsste schon so Einiges. Deshalb bin ich ein erfahrener Entwickler Lässt sich alles mit den 10-Zeilern hier erledigen.

Aber ich gehe mal davon aus, das Du deinen Code nicht als minimalistisch-kompaktes Beispiel hier eingestellt hast, das dieses Piddy-Problem realitätsnah umsetzt.

Dein Beispiel taugt aber durchaus als gutes Beispiel, denn im Kleinen soll man üben was einem im Großen gelingen soll.

Früher hieß das 'State-Pattern' übrigens DEA, und daran hatte ich auch gedacht, es aber verworfen, weil die Syntax einfach zu simpel ist und es fürs Parsen von Strings nun wirklich Standardlösungen gibt (aka RegEx).

Aber egal. Viele Wege führen nach Rom.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz