Jak rozdzielić łańcuch tekstowy wg. jakiegoś znaku

Adam Boduch

Osoby, które korzystają z Perla lub PHP znają zapewne funkcje Split (lub Explode), która umożliwia rozdzielenie łańcucha tekstowego na kilka części, według konkretnego znaku. Niestety w Delphi dla Win32 nie ma funkcji realizującej to zadanie. Do tego celu można użyć modułu zaprezentowanego w tej wskazówce.

Rozwiązanie #1

Oto moduł, który zawiera funkcje Split, dzięki której możesz rozdzielić łańcuch tekstowy:

(*

           b4p Project v. 1.1
           -----------
           Utworzenie pliku: 28.06.2002 00:28
           Autorzy: Adam Boduch [[email protected]]

           -----------
           Modul SplitUnit
           http://4programmers.net
*)

unit SplitUnit;

(*
   Modul ten zawiera procedure Split, ktora rozdziela dane w Stringu wg. okreslonego
   znaku. 
*)

interface

uses Windows;

var
  KeyChar : Char = ' '; // znak wg. bedzie nastepywac rozdzielenie

type
  TSplit = array of String; // nowy typ danych okreslajacy tablice stringow

  procedure Split(Value : String; var Output : TSplit); // funkcja rozdzielajaca Split

implementation

procedure Split(Value : String; var Output : TSplit);
var
  iCount : Integer;

  procedure Explode;
  var
    Found : Integer;
  begin
    SetLength(Output, iCount+1);
    Found := Pos(KeyChar, Value); // najpierw nastepuje odnalezienie szukanego znaku

   { pozniej za pomoca funkcji Copy nastepuje skopiowanie czesci danych do elementu
     tablicy }
    Output[iCount] := Copy(Value, 1, Found -1);
    Delete(Value, 1, Found); // skopiowane juz dane zostaja ze stringa usuniete
    Inc(iCount);  // zwiększenie licznika

    Found := Pos(KeyChar, Value); // ponowne odszukanie znaku KeyChar
    if Found > 0 then Explode; // w razie znaleienia ponownie wywolaj te procedure
  end;
  
begin
{
   Funkcja Split powoduje rozdzielenie danych ze stringa na kilka(kilkanascie)
   elementow i przypisanie jej do tablicy Output. Procedura ta wywoluje inna - Explode,
   ktora to jest procedura rekurencyjna (o rekurencji mozesz poczytac m.in na stronie
   www.4programmers.net/Algorytmy ) i to ona ma kluczowe zadanie rozdzielenie lancucha.
}
  iCount := 0;
  SetLength(Output, 1); // okreslenie liczby elementow tablicy dynamicznej
  Insert(KeyChar, Value, Length(Value)+1); // dodanie na samym koncu lancucha ze stalej KeyChar

  Explode; // wywolanie funkcji rekurencyjnej
end;


end.

Przykład użycia:

var
  S : String;
  Output : TSplit;
begin
  S := DupeString('ala ', 1000); // utworzenie przykładowego ciągu

  Split(S, Output); // tablica Output zawiera rozdzielony ciąg
end.

Rozwiązanie #2

Można również wykorzystać funkcję przedstawioną poniżej, która według testów działa znacznie szybciej. Rozdzielone łańcuchy przypisywane są jako elementy klasy TStrings:

procedure Split(Str: string;  SubStr: string; List: TStrings);
var
  I: Integer;
  S, Tmp: string;
begin
  List.Clear;
  S := Str;
  while Length(S) > 0 do
  begin
    I := Pos(SubStr, S);
    if I = 0 then
    begin
      List.Add(S);
      S := '';
    end
    else
    begin
      if I = 1 then
      begin
        List.Add('');
        Delete(S, 1, Length(SubStr));
      end
      else
      begin
        Tmp := S;
        Delete(Tmp, I, Length(Tmp));
        List.Add(Tmp);
        Delete(S, 1, I + Length(SubStr) - 1);
        if Length(S) = 0 then
          List.Add('');
      end;
    end;
  end;
end;

Parametr S musi zawierać ciąg do rozdzielenia natomiast SubStr - ciąg na podstawie którego łańcuch zostanie rozdzielony.

Rozwiązanie nr #3

Funkcja ExtractStrings zadeklarowana jest w module Classes. Jej użycie jest proste. Poniższy kod rozdziela łancuch na podstawie znaków spacji:

procedure TMyForm.MyButtonClick(Sender: TObject);
const
  Foo = 'To jest łańcuch który zostanie rozdzielony';
var
  S : TStrings;
  i : Integer;
begin
  S := TStringList.Create;
  ExtractStrings([' '], [], Foo, S);

  for I := 0 to S.Count -1 do
    Memo1.Lines.Add(S[i]);

  S.Free;
end;

Zobacz też:

5 komentarzy

Adam dziękuję,
Co prawda 'Explode' mam w troszkę innej wersji ... (także z php) ale... szukam kodu dla implode plus example jak to użyć. Masz może jakieś sugestie odnośnie?
Pozdrawiam Henryk

" Niestety w Delphi dla Win32 nie ma funkcji realizującej to zadanie."

Adam, doucz sie:-)

ExtractStrings jest.

Adam, co my bysmy bez ciebie zrobili :)

adam dzieki za kodzik