Autor Beitrag
LuMa86
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: So 29.09.13 00:29 
Man könnte da jetzt mit StringReplace hantieren, das ist aber relativ langsam. Wie ist es hiermit?
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: So 29.09.13 01:45 
user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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.

ausblenden volle Höhe 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;// hier  call fpc_ansistr_unique versteckt, auch wenn es hier keinen Sinn macht
      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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: So 29.09.13 14:21 
Dann ersetzt man eben
ausblenden Delphi-Quelltext
1:
PCurrent := CharNext(PCurrent);					

durch
ausblenden Delphi-Quelltext
1:
inc(PCurrent);					

(äquivalent natürlich auch die anderen Stellen), und schon geht es auch unter Linux.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mo 30.09.13 08:46 
user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
..., 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: 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! :)