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 1 von 3  1 23      
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Parsen von Seitenzahlen

  Alt 19. Jul 2009, 11:47
Hallo,

ich habe schon die Suchfunktion sowohl vom Forum als auch von bekannten Suchmaschinen genutzt - leider ohne Ergebnis. Eventuell habe ich auch die falschen Suchbegriffe benutzt. Falls das Thema woanders besser hinpasst, dann bitte ich die Moderatoren, das mal zu verschieben:

Ich drucke mit einem Programm viele Bilder. Dabei möchte ich jetzt dem Benutzer die Möglichkeit geben, über ein Edit-Feld die zu druckenden Seiten auszuwählen. Das bieten im Grunde alle Textprogramme, Adobe Reader etc. an. Wenn also z.B: "1-3; 10; 17; 21-23" angegeben wird, dann sollen nur die 8 Seiten 1, 2, 3, 10, 17, 21, 22 und 23 ausgedruckt werden. Wie man Strings zerlegt etc. ist bekannt. Ich habe nur leider Probleme, auf einen Lösungsansatz zu kommen. Ich erwarte keinen fertigen Code.

Ich bin für Tipps (auch Suchbegriffe s.o.) dankbar. Schönen Sonntag noch

Alex
Alex Winzer
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#2

Re: Parsen von Seitenzahlen

  Alt 19. Jul 2009, 11:54
Deklariere eine 'Liste von Seitenzahlen'
Zerteile die Seitenzahlangabe in Teilstrings, die durch ';' getrennt sind.
Jeder Teilstring ist entweder eine Seitenzahl oder ein Bereich.
Eine Seitenzahl besteht nur aus Ziffern. Hänge die einzelne Seitenzahl in die Liste.
Ein Bereich ist eine Seitenzahl gefolgt von einem '-' gefolgt von einer Seitenzahl. Hänge alle Seitenzahlen zwischen der ersten und der Zweiten in die Liste.

Drucke alle in der Liste befindlichen Seiten.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
TurboMartin

Registriert seit: 13. Feb 2006
Ort: Bad Honnef
765 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Parsen von Seitenzahlen

  Alt 19. Jul 2009, 11:57
Z.B. das hier oder ganz allgemein Hier im Forum suchenexplode/explodeexplode
Tomorrow will be cancelled due to lack of interest.

  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Parsen von Seitenzahlen

  Alt 20. Jul 2009, 00:03
Hallo alzaimar und TurboMartin! Danke für Eure Hilfe!

Die Sache mit explode etc. ist mir zu kompliziert, auch wenn sie vermutlich dasselbe macht wie ich. Auch bei der Suche mit dem Suchwort explode habe ich immer nur etwas zum Zerteilen von Strings gefunden. Aber
Zitat von Schwedenbitter:
Wie man Strings zerlegt etc. ist bekannt.
Ich habe es jetzt nach dem Schema von alzaimar gelöst. Den Quellcode habe ich beigefügt, falls nochmal jemand das Bedürfnis hat, bestimmte Seiten zu drucken oder sonstwas damit zu machen. Eine Fehlerbehandlung ist nicht dabei, wird in meinem kompletten Programm über die Abfrage der Eingabe beim Edit-Feld gemacht.
Für Ratschläge und insbesondere Verbesserungen bin ich trotzdem immer noch zu haben.

Kann mir bitte noch jemand sagen, ob es (1) eine Möglichkeit gibt, mein Array Of Boolean als offenes Array zu deklarieren und (2) ob mir das speichermäßig Ersparnisse/Vorteile bringt?

Gruß, Alex
Angehängte Dateien
Dateityp: zip parser_p_878.zip (1,8 KB, 15x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
20. Jul 2009, 06:33
Dieses Thema wurde von "mkinzler" von "Programmieren allgemein" nach "VCL / WinForms / Controls" verschoben.
Scheint ein Delphi-Problem zu sein
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#6

Re: Parsen von Seitenzahlen

  Alt 20. Jul 2009, 07:57
Zitat von Schwedenbitter:
Kann mir bitte noch jemand sagen, ob es (1) eine Möglichkeit gibt, mein Array Of Boolean als offenes Array zu deklarieren und (2) ob mir das speichermäßig Ersparnisse/Vorteile bringt?
Seiten: Array of Boolean;

und dann mit SetLength die Größe ändern

Vorteile bringt es dann, wenn es z.B. nur 10 statt 1000 Seiten, da dann ja auch nur 10 Byte im Array nötig sind, + ~12 Byte für die Speicherverwaltung

so ist das Array ja 1000 Byte groß (Boolean = 1 Byte)
obwohl 1 KB jetzt nicht soooooo groß ist.

mehr Speicher könnte man nur noch mit einem SET bzw. einer Bitmaske sparen (1 Bit pro Seite)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Parsen von Seitenzahlen

  Alt 20. Jul 2009, 08:23
Hallo Alex,

Ein Alternativ-Vorschlag:
Folgende Routine liefert mir den ersten Teilstring bis zu einem Trenner, oder den ganzen String, wenn es kein Trenner mehr gibt. Gleichzeitig wird der String um den ersten Teilstring verkürzt.
Delphi-Quellcode:
Funtion ExtractString (Var aString : String; Const aDelimiter : String) : String;
Var
  P : Integer;

Begin
  P := Pos(aDelimiter, aString);
  If P=0 Then Begin
    Result := Trim (aString);
    aString := '';
  End
  Else Begin
    Result := Trim (Copy (1, p-1));
    aString := Trim (Copy (aString, p+Length(aDelimiter), MaxInt));
  End
End;
(*
s := '12;345';
t := ExtractString(s,';'); // Liefert t<-'12' und s<-'345'
t := ExtractString(s,';'); // Liefert t<-'345' und s<-''
*)
Nun kann ich die Eingabe also Stück für Stück abarbeiten. O.g. Funktion verwende ich in fast jedem Programm irgendwo, sie ist ungeheuer praktisch.
Delphi-Quellcode:
Type
  TBooleanDynArray = Array Of Boolean;
...
Procedure CreatePageNumbers (aPageNumberDesc : String; Var aPagesToPrint : TBooleanDynArray);
Var
  pageDesc,
  rangeStart : String;
  pagenumber, p, q : Integer;

Begin
  If aPageNumberDesc = 'Then // Initialisieren: Wenn Beschreibung leer ist,...
    For p := Low(aPagesToPrint) To High (aPagesToPrint) Do // ...dann sollen alle Seiten gedruckt werden
      aPagesToPrint[p] := True
  else // Sonst sollen erstmal keine Seite gedruckt werden
    For p := Low(aPagesToPrint) To High (aPagesToPrint) Do
      aPagesToPrint[p] := False;

  While aPageNumberDesc<>'do Begin // Solange noch etwas in der Seitenangabe drin steht
    pageDesc := ExtractString (aPageNumberDesc,';'); // Nächsten Teilstring holen
    If TryStrToInt (pageDesc, pagenumber) Then // Teilstring = einzelne Zahl => Zur Liste hinzufügen
      aPagesToPrint[pageNumber] := True
    else Begin
      rangeStart := ExtractString (pageDesc,'-'); // 1.Teil von <Seite> - <Seite>
      If TryStrToInt (pageDesc,q) And TryStrToInt (rangeStart,p) Then // Prüfen, ob zwei Nummern vorhanden sind
        For pageNumber := p to q Do // Ja, also alle Zahlen in die Liste hinzufügen
          aPagesToPrint[pageNumber] := True
      Else // Keine gültige Bereichsangabe
        Raise Exception.Create('Ungültige Angabe'); // Exception und Ende
    End
  End
End;
Wie Du siehst, habe ich die Funktion vollständig vom Programm und ihren Strukturen getrennt. Damit ist diese Funktion allgemeingültig und kann in jedem Projekt unmittelbar wiederverwendet werden. Durch die Verlagerung der Problemlösung 'Teilstring extrahieren' ist die Routine auch lesbarer, finde ich.

P.S.: Die Prüfung, ob bei einer Bereichsangabe 'a-b' der Wert a < b ist, habe ich mir erspart, das kannst Du gerne noch implementieren.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#8

Re: Parsen von Seitenzahlen

  Alt 20. Jul 2009, 09:56
Es gibt da noch die Klasse TBits, die IMHO angenehmer und platzsparender ist.

Aber ganz perfekt wäre es so:
1.) string in einzelstücke zerlegen (explode & co)
2.) TSeitenEintrag = record von,bis:integer end; ein array of TSeitenEintrag anlegen und befüllen.
3.) dieses Array sortieren (einfaches Selection Sort reicht aus)
4.) Optimieren. Array von hinten nach vorne durchgehen und schauen,
ob man anliegende oder überschneidende Seiten von zwei auf einen Eintrag reduzieren kann
dieser Schritt ist optional
5.) Suchfunktion schreiben, die array durchläuft und schaut ob es einen Treffer gibt
6.) Punkt 1.) bis 5.) als wiederverwendbare Klassse implementieren

Diese Vorgehensweise kann auch folgende Anweisung problemlos umsetzen:
Code:
1-5;60-
Das wären die Seiten 1 bis 5 und 60 bis Ende.

Nachtrag:
die Klasse bekommt zusätzlich die Boolean Properties EvenPages und OddPages.
Die Suchfunktion von 5.) berücksichtigt diese Flags.
Somit können auch "nur gerade Seiten" oder "nur ungerade Seiten" von nur einer
Klasse behandelt werden.
fork me on Github
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: Parsen von Seitenzahlen

  Alt 20. Jul 2009, 19:57
Zitat von sx2008:
Aber ganz perfekt wäre es so:
...
Definiere "perfekt"

Zitat von sx2008:
Diese Vorgehensweise kann auch folgende Anweisung problemlos umsetzen:
Code:
1-5;60-
Das können die anderen -nach entsprechender Modifizierung- auch.
Bei mir wäre dies eine Zeile:
Delphi-Quellcode:
...
    else Begin
      rangeStart := ExtractString (pageDesc,'-');
      If pageDesc='Then pageDesc := IntToStr (TotalPageCount); // <<--- Die Erweiterung
...
End;
Die Erweiterung der Spezifikation um gerade/ungerade Seiten ließe sich durch eine einfache Fallunterscheidung ebenfalls leicht implementieren.

Wie gesagt: Einen Vorteil Deiner Methode sehe ich nicht. Aber das heißt ja nicht, das es ihn nicht gibt. Erstelle doch einfach mal so eine Klasse. Ich befürchte, sie ist ein wenig komplexer als mein 10-Zeiler. Ich befürchte auch, das sie wesentlich langsamer ist. Obwohl das wohl keine große Rolle spielen dürfte.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
673 Beiträge
 
#10

AW: Parsen von Seitenzahlen

  Alt 17. Aug 2012, 16:40
Da ich derartiges in meinem Projekt benötige, habe ich den Ansatz von alzaimar übernommen. Ich nutze aber eine Integerliste. Zusätzlich habe ich eine Umkehrung mit CreateNumberString hinzugefügt. Hier wird aus einer Integerliste ein String erstellt.
Vielleicht kann es jemand irgendwann mal gebrauchen.
Gruss Jens

Delphi-Quellcode:
unit tools.ParseNumbers;
// http://www.delphipraxis.net/934335-post7.html

interface

uses
  System.Generics.Collections;

function ExtractString(Var aString: string; const aDelimiter: string): string;
function CreateNumberList(aNumberDesc: string; aNumberList: TList<Integer>): Boolean;
procedure CreateNumberString(var aNumberDesc: string; aNumberList: TList<Integer>);

const
  ValidCharsString = ' ,;-0123456789';

implementation

uses
  System.SysUtils, System.StrUtils;

function ExtractString(Var aString: string; const aDelimiter: string): string;
Var
  P: Integer;
Begin
  P := Pos(aDelimiter, aString);
  If P = 0 Then
  Begin
    Result := Trim(aString);
    aString := '';
  End
  Else
  Begin
    Result := Trim(Copy(aString, 1, p - 1));
    aString := Trim(Copy(aString, p + Length(aDelimiter), MaxInt));
  End
End;

procedure TrimString(var s: string);
begin
  s := Trim(s);
  s := ReplaceStr(s, ' -', '-');
  s := ReplaceStr(s, '- ', '-');
  s := ReplaceStr(s, ',', ';');
  s := ReplaceStr(s, ' ;', ';');
  s := ReplaceStr(s, '; ', ';');
  s := ReplaceStr(s, ' ', ';');
end;

function CreateNumberList(aNumberDesc: string; aNumberList: TList<Integer>): Boolean;
Var
  numberDesc, rangeStart: String;
  number, p, q : Integer;
Begin
  aNumberList.Clear;
  TrimString(aNumberDesc);

  While aNumberDesc <> 'do
  Begin
    numberDesc := ExtractString(aNumberDesc, ';');

    If TryStrToInt(numberDesc, number) Then
      aNumberList.Add(number)
    else
    Begin
      rangeStart := ExtractString(numberDesc, '-');
      If TryStrToInt(numberDesc, q) And TryStrToInt(rangeStart, p) and (p <= q) Then
        For number := p to q Do
          aNumberList.Add(number)
      Else
        Exit(False);
    End
  End;
  Result := True;
End;

procedure CreateNumberString(var aNumberDesc: string; aNumberList: TList<Integer>);
var
  i: Integer;
begin
  if aNumberList.Count = 0 then
    Exit;
  aNumberDesc := '';
  aNumberList.Sort;
  i := 0;
  while (i < aNumberList.Count) do
  begin
    if (i + 2 < aNumberList.Count) and (aNumberList[i] + 1 = aNumberList[i + 1]) and
      (aNumberList[i] + 2 = aNumberList[i + 2]) then
    begin
      aNumberDesc := aNumberDesc + IntToStr(aNumberList[i]) + '-';
      while (i + 1 < aNumberList.Count) and (aNumberList[i] + 1 = aNumberList[i + 1]) do
        Inc(i);
      aNumberDesc := aNumberDesc + IntToStr(aNumberList[i]);
    end
    else
    begin
      aNumberDesc := aNumberDesc + IntToStr(aNumberList[i]);
    end;

    Inc(i);
    if i + 1 < aNumberList.Count then
      aNumberDesc := aNumberDesc + ';';
  end;
end;

end.
Achtung: Bin kein Informatiker sondern komme vom Bau.

Geändert von Jens01 (17. Aug 2012 um 16:56 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 23:55 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