Autor |
Beitrag |
LuMa86
      
Beiträge: 76
|
Verfasst: Sa 28.09.13 22:33
Hallo,
ich habe eigentlich ein recht simples Problem:
Ich lese ein PDF-Dokument in eine Memo ein, um es dann weiterzuverarbeiten. Dabei geht die Tabellenstruktur natürlich flötten, aber die einzelnen Lines, sind noch vorhanden, so wie im original Dokument. Allerdings befinden sich ohne erkennbares Muster Leerzeichen zwischen den einzelnen Wörter in einer Line. Mal 10, mal 50, mal 37. Es sind IMMER welche da, allerdings nie weniger als 3. Jetzt möchte ich alle Leerzeichen ersetzen, und zwar durch nur ein einziges Leerzeichen. So wird es zu einem ordentlich formatierten, lesbaren Text.
Jetzt stellt sich mir die Frage, wie ich das anstelle. Gibt es da eine einfache Methode oder würdet ihr es genauso wie ich machen: Eine Schleife durcheiern und Stelle für Stelle überprüfen?
Gruß,
LuMa
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 29.09.13 00:29
Man könnte da jetzt mit StringReplace hantieren, das ist aber relativ langsam. Wie ist es hiermit?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| function SingleBlanks(const Src: string): string; const BLANK = #32; STRING_END = #0; var PSrc, PDest, PCurrent: PChar; FirstBlank: Boolean; begin FirstBlank := true; SetLength(Result, Length(Src)); PSrc := PChar(Src); PDest := PChar(Result); PCurrent := PDest; while PSrc^ <> STRING_END do begin if (PSrc^ <> BLANK) or FirstBlank then begin PCurrent^ := PSrc^; FirstBlank := PSrc^ <> BLANK; PCurrent := CharNext(PCurrent); end; PSrc := CharNext(PSrc); end; SetString(Result, PDest, PCurrent - PDest); end; |
Für diesen Beitrag haben gedankt: LuMa86
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: So 29.09.13 01:45
WasWeißDennIch hat folgendes geschrieben : | Man könnte da jetzt mit StringReplace hantieren, das ist aber relativ langsam. |
Wenn es sich um AnsiStrings handelt, könnte man StringReplace durch eine schnellere Variante ersetzen: fastcode.sourceforge.net/
Das soll um den Faktor 10 - 15 schneller sein. Dennoch würde ich die Aufgabe mit einer Schleife realisieren, weil die Fastcode-Variante nicht mit Unicode und unter neueren Delphi-Versionen funktioniert.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: So 29.09.13 10:28
Hallo,
ich habe mal die Variante von WasWeißDennIch ohne Pointer umgeschrieben, weil ich unter Linux kein CharNext aus der Windows API habe, welches auch einen gewissen versteckten Aufwand hat.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55:
| {$IFDEF FPC} {$DEFINE RELEASE} {$MODE DELPHI} {$ELSE} {$APPTYPE CONSOLE} {$ENDIF} uses sysutils; const BLANK = ' '; function SingleBlanks(const Src: string): string; const BLANK = ' '; var srcPos,destPos: integer; srcChar : char; FirstBlank: Boolean; begin FirstBlank := true; SetLength(Result, Length(Src)); destPos := 1; For srcPos := 1 to length(Src) do begin srcChar := Src[srcPos]; if (srcChar<> BLANK) or FirstBlank then begin result[destPos] := srcChar; inc(destPos); FirstBlank := srcChar<> BLANK; end; end;
setlength(result,destpos-1); end;
var i : char; j: integer; s: string; Begin randomize; s := ''; For i := 'A' to 'Z' do begin s:= s+i; For j := 1 to random(10)+1 do s:= s+BLANK; end; writeln(s,'<'); writeln(SingleBlanks(s),'<'); end. |
Gruß Horst
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 29.09.13 14:21
Dann ersetzt man eben
Delphi-Quelltext 1:
| PCurrent := CharNext(PCurrent); |
durch
Delphi-Quelltext
(äquivalent natürlich auch die anderen Stellen), und schon geht es auch unter Linux.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Mo 30.09.13 07:39
Hallo,
da ich CharNext nicht kannte, hatte ich gedacht, es wäre ganz bewußt eingesetzt worden, weil es erst die Stelle auf die gezeigt wird auf <> #0 prüft und wenn es so ist, den Zeiger erhöht, sonst nicht.
Aber das braucht man hier ja eigentlich nicht, dann geht es auch mit inc(PCurrent);
Gruß Horst
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Mo 30.09.13 08:46
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Di 01.10.13 08:26
Hallo,
es ist nicht fatal, weil Du es selbst zuvor machst:
while PSrc^ <> STRING_END do
charNext verhindert bei konsequenter Verwendung wohl einen BufferOverrun, weil man nie über das Ende der Zeichenkette hinaus kommt.
Der Theadersteller kann ja von seinen Erfahrungen berichten.
Gruß Horst
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Di 01.10.13 08:30
Ja eben, diese Bedingung würde ja nie erfüllt, wenn der Zeiger bei #0 nicht erhöht wurde. Aber wir kommen vom Thema ab.
|
|
LuMa86 
      
Beiträge: 76
|
Verfasst: Do 03.10.13 11:12
Danke für eure Hilfe! Der COde aus WasWeißDennIch's Post funktioniert super  Geht mir nur um Windows, daher ist der Rest für mich nicht ganz so wichtig, aber danke für eure Mühe und Hilfe! 
|
|