Tmemorystream durchsuchen

Für Fragen von Einsteigern und Programmieranfängern...
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Tmemorystream durchsuchen

Beitrag von fliegermichl »

@warf
Toller Algorithmus!
Wäre die Wikipedia Seite so formuliert wie Deine Beschreibung, hätte ich sie auch verstanden. Ich weiss nicht, wieso die Schreiber bei Wikipedia ihre Artikel immer so formulieren, daß sie keine Sau (also ich zumindest) versteht.

malabarista
Beiträge: 321
Registriert: Sa 11. Jun 2016, 12:16
OS, Lazarus, FPC: Linux Mint 18.1 L1.6.2-1 FPC 3.0.0
CPU-Target: 64Bit
Wohnort: Konstanz

Re: Tmemorystream durchsuchen

Beitrag von malabarista »

Da gibt es leider noch einen Compiler-Fehler, den ich nicht verstehe:

>> if pattern.chars = buff[state] then

Error: Wrong number of parameters specified for call to "GetChar"
Error :Found declaration : GetChar(longint):Char

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Tmemorystream durchsuchen

Beitrag von braunbär »

Pattern ist vom Datentyp string - was pattern.chars bedeuten soll, ist mir völig unklar.
Ich weiss zwar, dass man mittlerweile einige String-Funtionen in OOP-Syntax schreiben kann, also statt length(patterm) pattern.length, aber mit pattern.chars kann ich nichts anfangen.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Tmemorystream durchsuchen

Beitrag von theo »

https://www.freepascal.org/docs-html/rt ... elper.html

Der Code von Warf ist wahrscheinlich zum selber fertigtüfteln gedacht. ;-)
Bei mir funzt es mal so mit (Nur kurz etwas weiter gehackt).

Code: Alles auswählen

function findInStream(Str: TSTream; pattern: string): integer;
var
  State: integer;
 
  function searchMem(buff: PChar; buffSize: integer): integer;
  begin
    for Result := 0 to buffSize - 1 do
    begin
      if pattern.chars[state] = buff[Result] then
        Inc(state)
      else
        state := 0;
      if State = pattern.length then
      begin
        break;
      end;
    end;
  end;
 
var
  buff: array[0..1023] of char;
  len: integer;
begin
  Str.Position := 0;
  State := 0;
  Result := 0;
  if (Str is TMemoryStream) then
  begin
    with TMemoryStream(Str) do
      Result := searchMem(Memory, Size);
    if State = pattern.length then
    begin
      Dec(Result, pattern.length - 2);
      exit;
    end;
    Result := -1;
  end
  else
    repeat
      len := Str.Read(buff[0], 1024);
      Inc(Result, searchMem(@buff[0], len));
      if State = pattern.length then
      begin
        Dec(Result, pattern.length - 2);
        exit;
      end;
    until len < 1024;
  Result := -1;
end;

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Tmemorystream durchsuchen

Beitrag von braunbär »

Danke für den Link. Zumindest kenne ich fortan "chars".
Was es bringen soll, z.B. pattern.chars{5] an Stelle von pattern[6] zu schreiben, erschließt sich mit zwar nicht, aber irgendwer hat sich sicher etwas dabei gedacht... :D

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Tmemorystream durchsuchen

Beitrag von Warf »

theo hat geschrieben:Der Code von Warf ist wahrscheinlich zum selber fertigtüfteln gedacht. ;-)
Bei mir funzt es mal so mit (Nur kurz etwas weiter gehackt).

Ja hab den ohne Compiler, etc. ausm kopf geschrieben

braunbär hat geschrieben:Danke für den Link. Zumindest kenne ich fortan "chars".
Was es bringen soll, z.B. pattern.chars{5] an Stelle von pattern[6] zu schreiben, erschließt sich mit zwar nicht, aber irgendwer hat sich sicher etwas dabei gedacht... :D


Ganz einfach, die TStringHelper Funktionen sind alle 0 Basiert, während die normalen funktionen (pos, strutils funktionen, etc.) alle 1 basiert sind. Aber ich arbeite in dem Beispiel mit einer Array-Pointer (also einem Pointer den ich als Dyn Array verwende), und der ist 0 basiert. Bevor ich also irgendwo fehler drin hab weil ich irgendwo ein +1 oder -1 vergessen hab, nehm ich lieber die Helper Funktionen und alles funktioniert gleich.
Was man verwenden will kann man aber selbst entscheiden, man sollte nur bei einem bleiben (also wenn man chars verwendet dann auch str.IndexOf statt pos, etc.), und persönlich (also auch wenn es sich nicht wie in dem beispiel expliziet anbietet) bevorzuge ich den StringHelper, u.a. da bei Str. + Strg+Leer mir die Lazarus vervollständigung alle Möglichen Funktionen anzeigt, ist aber nur eine persönliche präferenz. Kann jeder machen wie er Lustig ist.

Antworten