Autor Beitrag
sahib
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: Di 31.05.05 02:08 
Hi.

Ich habe eine Textdatei in einen TMemoryStream eingelesen und durchforste den Speicherbereich nun nach mir wichtigen Daten. Ich hatte ähnliches schon einmal mit einer TStringList gemacht. Aber das war sehr speicherintensiv und auch nicht sonderlich schnell.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var
  Stream: TMemoryStream;
  p, q: PChar;  // oder PByte?
begin
  // Zeiger p auf Anfang
  p := Stream.Memory;

  // [...] Suchfunktion à la if p^ = '/' then...
  // q zeigt auf Ende des interessanten Bereichs,
  // als Bsp.:
  q := p + 100;
end;

Jetzt habe ich aber das Problem, den Bereich zwischen p und q in einen String oder PChar (vielleicht besser?) zu bekommen. Wie kann ich das anstellen? Bei mir kommet immer nur das CPU-Fenster :( Ich könnte Zählvariablen mitlaufen lassen und dann mit Move arbeiten. Aber ich müsste doch mit den Pointern selber rechnen können, oder?

Christian
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 31.05.05 04:53 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TForm1.Button1Click(Sender: TObject);
var
  ms: TMemoryStream;
  p: PChar;
begin
  ms := TMemoryStream.Create;
  try
    ms.LoadFromFile('d:\Dokumente\Träume vom 2004-02-25.txt');
    p := ms.Memory;
    while p^ <> #0 do
    begin
      ShowMessage(p^);
      Inc(p);
    end;
  finally
    FreeAndNil(ms);
  end;
end;

Gibt dir jedes Zeichen einzeln in dem Dialog aus. Nachteil: Du kannst keine AnsiStrings verwenden, da in AnsiStrings auch das #0 Zeichen vorkommen kann, bei PChar's ist es das Stringende-Zeichen.

Erweiterung:
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:
procedure TForm1.Button1Click(Sender: TObject);
var
  ms: TMemoryStream;
  p, q, r: PChar;
  i: Integer;
  s: string;
begin
  i := 0;
  ms := TMemoryStream.Create;
  try
    ms.LoadFromFile('d:\Dokumente\Träume vom 2004-02-25.txt');
    p := ms.Memory;
    q := p;
    r := p;
    while p^ <> #0 do
    begin
      if p^ = 'd' then
      begin
        // drei Zeichen weiter gehen mit dem einen Zeiger
        Inc(q, 3);
        // einen zurück mit dem anderen Zeiger
        Dec(r, 1);
        // wenn Leerzeichen dahinter und davor
        if (q^ = #32and (r^ = #32then
        begin
          // Zeichenfolge in String kopieren
          SetString(s, p, q - r - 1);
          // auf bestimmten Artikel prüfen
          if (s = 'der'or (s = 'das'or (s = 'die'then
          begin
            ListBox1.Items.Add(s);
            // Zähler erhöhen
            Inc(i);
          end;
        end;
        // Hilfs-Zeiger wieder mit Zeiger p synchronisieren
        Dec(q, 3);
        Inc(r);
      end;
      // alle "Zeichen"-Zeiger eins nach vorne setzen
      Inc(p);
      Inc(q);
      Inc(r);
    end;
  finally
    FreeAndNil(ms);
  end;
  // Anzahl der gefundenen Zeichenfolgen ausgeben
  ShowMessage(IntToStr(i));
end;

Zählt dir alle bestimmten Artikel (der, die, das) in einem Text.

Ich weiß nicht, was du vor hast, aber es wäre zu überlegen, ob du dich nicht mal über Reguläreausdrücke schlau machst.
sahib Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: Di 31.05.05 09:48 
Danke Michael.

Die Funktion SetString fehlte mir, da muss ich mal ein wenig nachlesen. Ich hatte erst mit Move gearbeitet und dabei falsche Daten erhalten. An das schlau machen bezüglich regulärer Ausdrücke dachte ich auch schon, aber das ist ja auch so eine Wissenschaft für sich. Erste Gehversuche meinerseits waren beschämend. Dass sie zweifelsohne mächtiger sind, als selbstgeschriebene Routinen zum auffinden von Texten, ist klar. Wie sieht das aber mit der Geschwindigkeit aus? Das Übersetzen des Ausdrucks nimmt ein wenig Zeit in Anspruch, das sollte aber kein Problem sein, weil der für die Datei gleich bliebe und so nicht in der innersten Schleife verweilte. Die TRegExpr von Andrey V. Sorokin macht einen guten Eindruck.

Christian
deccer
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 57



BeitragVerfasst: Di 31.05.05 09:55 
Move funktioniert ähnlich wie SetString :)

ausblenden Quelltext
1:
Move(Pointer(sZielString)^, pDeinPointer^, iAnzahlAnBytesOderDieLaengeDieDerStringHabenSoll);					


oder

ausblenden Quelltext
1:
2:
SetLength(sZielString, iAnzahlAnBytesOderDieLaengeDieDerStringHabenSoll);
Move(sZielString[1], pDeinPointer^, iAnzahlAnBytesOderDieLaengeDieDerStringHabenSoll);
sahib Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: Di 31.05.05 10:33 
Hallo deccer.

Ersteres Code-Schnipsel sieht ja lecker aus - muss ich mal testen. Ich dachte, dass ich immer wie im zweiten Beispiel vorgehen müsste, nämlich der Initialisierung der Stringlänge. Aber wenn das wie im ersten klappt... ;)

*edit* Ok, reguläre Ausdrücke mit der von mir erwähnten Unit sind viel zu langsam.

Christian