Home » Tutorials » Object Pascal/RTL » Stringverarbeitung

Stringverarbeitung

StringFunktionen selbst gemacht

Bisher haben wir nur vorhandene Delphi-Funktionen benutzt. Jetzt schauen wir uns auch einmal an, wie diese funktionieren und wie man so etwas selbst machen kann.
Dazu schreiben wir uns eine Funktion, die Delphi noch nicht kennt, die aber trotzdem ganz nützlich sein könnte:
Pos sucht ja genau das erste Vorkommen eines Teilstrings im String. Als Variante davon wollen wir nun eine Funktion LastPos() schreiben, die das letzte Vorkommen ermittelt.
Wie soll diese Funktion nun aufgebaut sein? Genau das ist es, was wir uns zu allererst überlegen müssen. In Anlehnung an Pos definieren wir die Parameter sowie den Rückgabewert von LastPos:

function LastPos(const SubStr, S: string): Integer;

SubStr: der String, nach dem gesucht werden soll
S: der String, in dem gesucht werden soll
Rückgabewert: die Position des letzten Vorkommens; ansonsten 0
Um so etwas zu realisieren, brauchen wir zunächst mal eine Idee. Möglichkeiten gibt es da mehrere. Eine wäre, so lange mit PosEx zu suchen, bis PosEx nichts mehr findet. Dann hat man das letzte Vorkommen. Das ist allerdings nicht sehr performant (funktioniert aber), da auch bei extrem langen Strings von vorne gesucht wird. Wer jetzt einwendet, dass die Geschwindigkeitsvorteile bei heutigen Computern vernachlässigbar seien, dem kann ich nur sagen: Ja, in den meisten Fällen schon. Wenn man das aber das ganze hunderte Mal hintereinander machen muss (Logauswertung z.B.), kann das schon ins Gewicht fallen und außerdem – der eigentliche Hauptgrund – wollen wir hier was lernen… 😉
Wir brauchen also eine neue Idee. Da wir das letzte Vorkommen suchen wollen, bietet es sich an, den String rückwärts zu durchsuchen. Und genau das machen wir auch. Wir gehen den String rückwärts durch und vergleichen ihn mit dem Substring. Dabei müssen wir nur darauf achten, dass wir den Substring auch von hinten durchgehen, da das letze Zeichen ja von hinten gesehen das erste ist.
Wenn die Idee nun klar ist, können wir uns nun auch der Implementierung widmen:

function LastPos(const SubStr, S: string): Integer;
var
  i: Integer;
  j: Integer;
begin
  Result := 0;    // noch nicht gefunden
  i := Length(S);
  j := Length(SubStr);

  while (i >= 1) and (j >= 1) do
  begin
    if S[i] = SubStr[j] then  // passt das Zeichen?
    begin
      // nächstes Zeichen untersuchen
      Dec(j);
    end
    else
    begin
      // wieder mit letztem SubStr-Zeichen anfangen
      i := i + Length(SubStr) - j;
      j := Length(SubStr);
    end;

    if j = 0 then
    begin
      Result := i;  // gefunden
    end;

    Dec(i); // nächstes Zeichen
  end;
end;

Wie funktioniert das Ganze jetzt? Das Prinzip ist eigentlich ganz einfach. Wir haben zwei Laufvariablen i und j. i läuft in S, j in SubStr und zwar jeweils von hinten nach vorne (wir wollen ja das letzte Vorkommen ermitteln). Wurde eine Übereinstimmung gefunden, wird j dekrementiert, d.h. wir testen dann auf Übereinstimmung mit dem zweitletzten Zeichen. Dann mit dem drittletzten, usw. Stimmt ein Zeichen nicht mit dem gesuchten überein, so wird wieder von vorne…äh… hinten angefangen, also wieder mit dem letzen Zeichen von SubStr. Irgendwann wird der Substring gefunden und i als Position zurückgegeben. Wird der Substring nicht gefunden, bleibt Result 0.
So, nun sind wir am Ende dieses kleinen Tutorials. Und viel mehr gibt es auch über die Stringverarbeitung nicht zu sagen. Eigentlich alles ganz einfach… 😉