Entwickler-Ecke
Sonstiges (Delphi) - Leerzeichen aus String entfernen (außer eins)
LuMa86 - Sa 28.09.13 22:33
Titel: Leerzeichen aus String entfernen (außer eins)
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 - 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; |
Gerd Kayser - 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:
http://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 - 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.
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: 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 - So 29.09.13 14:21
Dann ersetzt man eben
Delphi-Quelltext
1:
| PCurrent := CharNext(PCurrent); |
durch
(äquivalent natürlich auch die anderen Stellen), und schon geht es auch unter Linux.
Horst_H - 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 - Mo 30.09.13 08:46
Horst_H hat folgendes geschrieben : |
..., weil es erst die Stelle auf die gezeigt wird auf <> #0 prüft und wenn es so ist, den Zeiger erhöht, sonst nicht. |
Das wäre für meine Funktion aber fatal, da es eine Endlosschleife bewirken würde ;)
Horst_H - 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 - 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 - 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! :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!