Podziel ciąg na tablicę ciągów na podstawie separatora

84

Próbuję znaleźć funkcję Delphi, która podzieli ciąg wejściowy na tablicę ciągów na podstawie ogranicznika. Znalazłem wiele w Google, ale wydaje się, że wszystkie mają swoje własne problemy i nie byłem w stanie zmusić żadnego z nich do działania.

Muszę tylko podzielić ciąg, taki jak "word:doc,txt,docx":, na tablicę opartą na ':'. Wynik byłby ['word', 'doc,txt,docx'].

Czy ktoś ma funkcję, o której wiedzą, że działa?

Dziękuję Ci

Ryan
źródło

Odpowiedzi:

86

można użyć właściwości TStrings.DelimitedText do podzielenia ciągu

sprawdź tę próbkę

program Project28;

{$APPTYPE CONSOLE}

uses
  Classes,
  SysUtils;

procedure Split(Delimiter: Char; Str: string; ListOfStrings: TStrings) ;
begin
   ListOfStrings.Clear;
   ListOfStrings.Delimiter       := Delimiter;
   ListOfStrings.StrictDelimiter := True; // Requires D2006 or newer.
   ListOfStrings.DelimitedText   := Str;
end;


var
   OutPutList: TStringList;
begin
   OutPutList := TStringList.Create;
   try
     Split(':', 'word:doc,txt,docx', OutPutList) ;
     Writeln(OutPutList.Text);
     Readln;
   finally
     OutPutList.Free;
   end;
end.

AKTUALIZACJA

Zobacz ten link, aby uzyskać wyjaśnienie StrictDelimiter.

RRUZ
źródło
22
Niestety w wielu "starszych" wersjach Delphi jest błąd (nie wiadomo, w której wersji został on naprawiony), który powoduje, że znak spacji jest zawsze używany jako separator. Więc obchodź się z tym ostrożnie !!
Leo
16
Tak. Będziesz chciał ustawić StrictDelimiter na true, a jeśli właściwość StrictDelimiter nie jest dostępna w twojej wersji Delphi, nie używaj tej techniki! Ale jeśli tak jest, jest to bardzo przydatne.
Mason Wheeler,
3
To nie był błąd, to była (irytująca) decyzja projektowa z czasów D1 lub D2. CommaText miał ująć wszystkie pola spacjami w cudzysłowy. Jeśli dane wejściowe zawierają podwójne cudzysłowy wokół dowolnych pól ze spacjami, wynik jest poprawny.
Gerry Coll
1
Jedną z moich irytacji jest niepotrzebne umieszczanie wskaźników typu w nazwach zmiennych / parametrów. Pascal jest silnie wpisany na maszynie - jest to zbędne wpisywanie (z odmiany ćwiczeń palców) i mylące, gdy wskaźnik typu jest nieprawidłowy, jak w tym przypadku: ArrayOfStrings nie jest tablicą (i jako taka nie odpowiada nawet na zadane pytanie) .
Deltics
6
Dla wszystkich, którzy głosują za tą odpowiedzią, pamiętaj, że nie daje ona tablicy, jak określono w pytaniu. Niekompletna specyfikacja wymagań jest dużym problemem w tej branży, ignorowanie określonych wymagań i dostarczanie czegoś, o co nie prosiliśmy, to kolejny duży problem. Akceptacja jednego z nich po prostu zachęca do złych praktyk. ;)
Deltics Kwietnia
67

Nie ma potrzeby tworzenia Splitfunkcji. To już istnieje, zob Classes.ExtractStrings.

Używaj go w następujący sposób:

program Project1;

{$APPTYPE CONSOLE}

uses
  Classes;

var
  List: TStrings;
begin
  List := TStringList.Create;
  try
    ExtractStrings([':'], [], PChar('word:doc,txt,docx'), List);
    WriteLn(List.Text);
    ReadLn;
  finally
    List.Free;
  end;
end.

I w pełni odpowiedzieć na to pytanie; Listreprezentuje żądaną tablicę z elementami:

List[0] = 'word'
List[1] = 'doc,txt,docx'
NGLN
źródło
14
ExtractStrings jest bardzo nieelastyczny: "Powrót karetki, znaki nowego wiersza i znaki cudzysłowu (pojedyncze lub podwójne) są zawsze traktowane jako separatory."; oraz „Uwaga: ExtractStrings nie dodaje pustych ciągów do listy”.
awmross
Problemem nie jest zaprojektowanie splitfunkcji, ale potrzeba TStringsobiektu. A ze względu na brak elastyczności (@awmross) wspomina, wolałbym rozwiązanie Franka
Wolf
50

Możesz użyć StrUtils.SplitString.

function SplitString(const S, Delimiters: string): TStringDynArray;

Jego opis z dokumentacji :

Dzieli ciąg na różne części rozdzielane określonymi znakami separatora.

SplitString dzieli ciąg na różne części rozdzielane określonymi znakami ogranicznika. S to ciąg do podzielenia. Separatory to ciąg zawierający znaki zdefiniowane jako separatory.

SplitString zwraca tablicę ciągów typu System.Types.TStringDynArray, która zawiera podzielone części oryginalnego ciągu.

Alex
źródło
3
Hmmm, nie w mojej wersji Delphi 2010 (istnieje procedura SplitString w XMLDoc i (jednostce Indy) IdStrings, ale żaden z nich nie robi tego, czego chce plakat, a procedura XMLDoc i tak nie jest ujawniana przez interfejs jednostki).
Deltics
3
function SplitString (const S, Delimiters: string): TStringDynArray; zdefiniowane w StrUtils.pas
alex
Nie mogę dołączyć pliku StrUtils.pas (nawet jeśli jest obecny).
poszukiwacz prawdy
To jest przykład podziału łańcucha na „tablicę”.
bvj
Najlepszą rzeczą jest to, że akceptuje to ogranicznik ciągów, a nie separatory znaków w innych odpowiedziach.
user30478,
42

Korzystanie z funkcji SysUtils.TStringHelper.Split , wprowadzonej w Delphi XE3:

var
  MyString: String;
  Splitted: TArray<String>;
begin
  MyString := 'word:doc,txt,docx';
  Splitted := MyString.Split([':']);
end.

Spowoduje to podzielenie ciągu z podanym separatorem na tablicę ciągów.

LU RD
źródło
18

Zawsze używam czegoś podobnego do tego:

Uses
   StrUtils, Classes;

Var
  Str, Delimiter : String;
begin
  // Str is the input string, Delimiter is the delimiter
  With TStringList.Create Do
  try
    Text := ReplaceText(S,Delim,#13#10);

    // From here on and until "finally", your desired result strings are
    // in strings[0].. strings[Count-1)

  finally
    Free; //Clean everything up, and liberate your memory ;-)
  end;

end;
Szczery
źródło
2
Świetne rozwiązanie dla użytkowników starszych wersji Delphi.
Wolf
Użytkownicy C ++ Builder 6: odpowiadająca jej funkcja toStrutils::AnsiReplaceText
Wolf
Niezwykle proste. Praca w Delphi 7 z: list.Text := AnsiReplaceStr(source, delimiter, #13#10);.
AlainD
W Delphi 6 można używać SysUtils.StringReplace
pyfyc
14

Podobna do funkcji Explode () oferowanej przez Mef, ale z kilkoma różnicami (z których jedną uważam za poprawkę błędu):

  type
    TArrayOfString = array of String;


  function SplitString(const aSeparator, aString: String; aMax: Integer = 0): TArrayOfString;
  var
    i, strt, cnt: Integer;
    sepLen: Integer;

    procedure AddString(aEnd: Integer = -1);
    var
      endPos: Integer;
    begin
      if (aEnd = -1) then
        endPos := i
      else
        endPos := aEnd + 1;

      if (strt < endPos) then
        result[cnt] := Copy(aString, strt, endPos - strt)
      else
        result[cnt] := '';

      Inc(cnt);
    end;

  begin
    if (aString = '') or (aMax < 0) then
    begin
      SetLength(result, 0);
      EXIT;
    end;

    if (aSeparator = '') then
    begin
      SetLength(result, 1);
      result[0] := aString;
      EXIT;
    end;

    sepLen := Length(aSeparator);
    SetLength(result, (Length(aString) div sepLen) + 1);

    i     := 1;
    strt  := i;
    cnt   := 0;
    while (i <= (Length(aString)- sepLen + 1)) do
    begin
      if (aString[i] = aSeparator[1]) then
        if (Copy(aString, i, sepLen) = aSeparator) then
        begin
          AddString;

          if (cnt = aMax) then
          begin
            SetLength(result, cnt);
            EXIT;
          end;

          Inc(i, sepLen - 1);
          strt := i + 1;
        end;

      Inc(i);
    end;

    AddString(Length(aString));

    SetLength(result, cnt);
  end;

Różnice:

  1. Parametr aMax ogranicza liczbę zwracanych ciągów
  2. Jeśli ciąg wejściowy jest zakończony separatorem, wówczas uznaje się, że istnieje nominalny „pusty” ciąg końcowy

Przykłady:

SplitString(':', 'abc') returns      :    result[0]  = abc

SplitString(':', 'a:b:c:') returns   :    result[0]  = a
                                          result[1]  = b
                                          result[2]  = c
                                          result[3]  = <empty string>

SplitString(':', 'a:b:c:', 2) returns:    result[0]  = a
                                          result[1]  = b

Jest to separator końcowy i hipotetyczny „pusty element końcowy”, który uważam za poprawkę błędu.

Dodałem również zasugerowaną przeze mnie zmianę alokacji pamięci, z doprecyzowaniem (błędnie zasugerowałem, że ciąg wejściowy może zawierać co najwyżej 50% separatorów, ale może oczywiście składać się ze 100% ciągów separatorów, dając tablicę pustych elementów!)

Deltics
źródło
7

Explode to bardzo szybka funkcja, alhoritm źródła pochodzi z komponentu TStrings. Do eksplodowania używam kolejnego testu: Explode 134217733 bajtów danych, otrzymuję 19173962 elementy, czas pracy: 2984 ms.

Implode to funkcja o bardzo niskiej prędkości, ale piszę to łatwo.

{ ****************************************************************************** }
{  Explode/Implode (String <> String array)                                      }
{ ****************************************************************************** }
function Explode(S: String; Delimiter: Char): Strings; overload;
var I, C: Integer; P, P1: PChar;
begin
    SetLength(Result, 0);
    if Length(S) = 0 then Exit;
    P:=PChar(S+Delimiter); C:=0;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
       Inc(C);
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
    SetLength(Result, C);
    P:=PChar(S+Delimiter); I:=-1;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
       Inc(I); SetString(Result[I], P1, P-P1);
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
end;

function Explode(S: String; Delimiter: Char; Index: Integer): String; overload;
var I: Integer; P, P1: PChar;
begin
    if Length(S) = 0 then Exit;
    P:=PChar(S+Delimiter); I:=1;
    while P^ <> #0 do begin
       P1:=P;
       while (P^ <> Delimiter) do P:=CharNext(P);
        SetString(Result, P1, P-P1);
        if (I <> Index) then Inc(I) else begin
           SetString(Result, P1, P-P1); Exit;
        end;
       while P^ in [#1..' '] do P:=CharNext(P);
       if P^ = Delimiter then begin
          repeat
           P:=CharNext(P);
          until not (P^ in [#1..' ']);
       end;
    end;
end;

function Implode(S: Strings; Delimiter: Char): String;
var iCount: Integer;
begin
     Result:='';
     if (Length(S) = 0) then Exit;
     for iCount:=0 to Length(S)-1 do
     Result:=Result+S[iCount]+Delimiter;
     System.Delete(Result, Length(Result), 1);
end;
Delphi 7
źródło
3
To się nie kompiluje: Stringsnie jest typem.
NGLN
7
var  
    su  : string;        // What we want split
    si  : TStringList;   // Result of splitting
    Delimiter : string;
    ...
    Delimiter := ';';
    si.Text := ReplaceStr(su, Delimiter, #13#10);

Linie na liście si będą zawierały podzielone ciągi.

Ihor Konovalenko
źródło
6

Możesz stworzyć własną funkcję, która zwraca TArray ciągu:

function mySplit(input: string): TArray<string>;
var
  delimiterSet: array [0 .. 0] of char; 
     // split works with char array, not a single char
begin
  delimiterSet[0] := '&'; // some character
  result := input.Split(delimiterSet);
end;
bob_saginowski
źródło
5

Oto implementacja funkcji eksploduj, która jest dostępna w wielu innych językach programowania jako funkcja standardowa:

type 
  TStringDynArray = array of String;

function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray; 
var 
  SepLen: Integer; 
  F, P: PChar; 
  ALen, Index: Integer; 
begin 
  SetLength(Result, 0); 
  if (S = '') or (Limit < 0) then Exit; 
  if Separator = '' then 
  begin 
    SetLength(Result, 1); 
    Result[0] := S; 
    Exit; 
  end; 
  SepLen := Length(Separator); 
  ALen := Limit; 
  SetLength(Result, ALen); 

  Index := 0; 
  P := PChar(S); 
  while P^ <> #0 do 
  begin 
    F := P; 
    P := AnsiStrPos(P, PChar(Separator)); 
    if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F); 
    if Index >= ALen then 
    begin 
      Inc(ALen, 5); 
      SetLength(Result, ALen); 
    end; 
    SetString(Result[Index], F, P - F); 
    Inc(Index); 
    if P^ <> #0 then Inc(P, SepLen); 
  end; 
  if Index < ALen then SetLength(Result, Index); 
end; 

Przykładowe użycie:

var
  res: TStringDynArray;
begin
  res := Explode(':', yourString);
Lew
źródło
2
W tym kodzie istnieją dziwne i potencjalnie nieefektywne opcje zarządzania / przewidywania długości wyniku. Zwiększając przyrostowo tablicę wyników, zwiększa się prawdopodobieństwo ponownej alokacji pamięci i fragmentacji. Bardziej efektywne byłoby ustawienie tak dużej początkowej długości, jak to możliwe, tj. Założenie, że ciąg wejściowy składa się z 50% ciągów separatorów = długość (S) div (2 * długość (separator)). Następnie należy ustawić rzeczywistą liczbę pozycje po
zakończeniu
Nie wyjaśniasz również celu parametru Limit. Intuicyjnie spodziewałem się, że ustawi maksymalną liczbę zwracanych podciągów, podczas gdy w rzeczywistości wydaje się, że ogranicza wykrywanie podciągów do pierwszej „Limit” liczby znaków w ciągu wejściowym. Wydaje się to bezcelowe, ponieważ jeśli musisz to zrobić, możesz po prostu wykonać funkcję Explode () na Copy () wymaganego podciągu. Użycie opcji Limit do ustawienia maksymalnej liczby podciągów byłoby znacznie bardziej przydatne.
Deltics
@Deltics: Nikt nie twierdził, że jest to wysoce zoptymalizowana funkcja i nikt o nią nie prosił, więc trochę nie rozumiem Twojej skargi. Ale może jesteś jednym z facetów, którzy optymalizują wszystko, bez względu na to, czy jest to konieczne, czy nie ...
Leo
1
Jestem typem faceta, który nie pisze niepotrzebnie nieefektywnego kodu, a potem martwi się o jego optymalizację. To nie był przypadek drobnej analizy kodu i znalezienia jakiegoś malutkiego potencjału optymalizacji, był to po prostu oczywista i łatwa do naprawienia nieefektywność: przyrostowy wzrost ciągłej pamięci, którą można zamiast tego łatwo wstępnie przydzielić, a następnie skrócić.
Deltics,
Również @Mef: I to nie była skarga, to był komentarz, obserwacja. Ale co ważniejsze, twój kod zawierał również to, co uważam za błąd (zobacz moją alternatywę dla wyjaśnienia).
Deltics,
5

Napisałem tę funkcję, która zwraca połączoną listę oddzielonych ciągów według określonego separatora. Czysty darmowy pascal bez modułów.

Program split_f;

type
    PTItem = ^TItem;
    TItem = record
        str : string;
        next : PTItem;
    end;

var
    s : string;
    strs : PTItem;

procedure split(str : string;delim : char;var list : PTItem);
var
    i : integer;
    buff : PTItem;
begin
    new(list);
    buff:= list;
    buff^.str:='';
    buff^.next:=nil;

    for i:=1 to length(str) do begin
        if (str[i] = delim) then begin
            new(buff^.next);
            buff:=buff^.next;
            buff^.str := '';
            buff^.next := nil;
        end
        else
        buff^.str:= buff^.str+str[i];
    end;
end;

procedure print(var list:PTItem);
var
    buff : PTItem;
begin
    buff := list;
    while buff<>nil do begin
        writeln(buff^.str);
        buff:= buff^.next;
    end;
end;

begin

    s := 'Hi;how;are;you?';

    split(s, ';', strs);
    print(strs);


end.
Aleš Oskar Kocur
źródło
3

Biblioteka kodów Jedi zapewnia ulepszoną listę StringList z wbudowaną funkcją Split, która może zarówno dodawać, jak i zastępować istniejący tekst. Zapewnia również interfejs zliczany referencyjnie. Więc może to być używane nawet ze starszymi wersjami Delphi, które nie mają SplitStrings i bez starannych i nieco żmudnych dostosowań standardowego TStringList, aby używać tylko określonych separatorów.

Na przykład podany plik tekstowy linii, takich jak Dog 5 4 7jeden, można przeanalizować za pomocą:

var slF, slR: IJclStringList; ai: TList<integer>; s: string; i: integer;
    action: procedure(const Name: string; Const Data: array of integer);

slF := TJclStringList.Create; slF.LoadFromFile('some.txt');
slR := TJclStringList.Create;
for s in slF do begin
    slR.Split(s, ' ', true);
    ai := TList<Integer>.Create;
    try
       for i := 1 to slR.Count - 1 do
           ai.Add(StrToInt(slR[i]));
       action(slR[0], ai.ToArray);
    finally ai.Free; end;
end; 

http://wiki.delphi-jedi.org/wiki/JCL_Help:IJclStringList.Split@string@string@Boolean

Arioch „The
źródło
3

To rozwiąże twój problem

interface
   TArrayStr = Array Of string;

implementation

function SplitString(Text: String): TArrayStr;
var
   intIdx: Integer;
   intIdxOutput: Integer;
const
   Delimiter = ';';
begin
   intIdxOutput := 0;
   SetLength(Result, 1);
   Result[0] := ''; 

   for intIdx := 1 to Length(Text) do
   begin
      if Text[intIdx] = Delimiter then
      begin
         intIdxOutput := intIdxOutput + 1;
         SetLength(Result, Length(Result) + 1);
      end
      else
         Result[intIdxOutput] := Result[intIdxOutput] + Text[intIdx];
   end;
end;
Dennis
źródło
Czy możesz wyjaśnić, co robi kod? Dzięki
Paco
przechodzi przez przekazany ciąg w poszukiwaniu stałej separatora, jeśli nie zostanie znaleziony, łączy się z bieżącą pozycją w tablicy, po znalezieniu przeskakuje do następnej pozycji w tablicy dynamicznej
Dennis
1

Moja ulubiona funkcja do dzielenia:

procedure splitString(delim: char; s: string; ListOfStrings: TStrings);
var temp: string;
    i: integer;
begin
   ListOfStrings.Clear;
   for i:=1 to length(s) do
    begin
      if s[i] = delim then
        begin
          ListOfStrings.add(temp);
          temp := '';
        end
      else
        begin
          temp := temp + s[i];
          if i=length(s) then
             ListOfStrings.add(temp);
        end;
    end;
    ListOfStrings.add(temp);
end;
John Boe
źródło
1
W twojej funkcji brakowało ostatniego elementu
alijunior
1
Musisz dodać ListOfStrings.add(temp);po pętli, aby dodać ostatni element.
rnso
Dzięki za notatkę, zredagowałem kod w bloku else.
John Boe,
0

*

//Basic functionality of a TStringList solves this:


uses Classes  //TStringList 
    ,types    //TStringDynArray
    ,SysUtils //StringReplace()
    ;

....

 //--------------------------------------------------------------------------
 function _SplitString(const s:string; const delimiter:Char):TStringDynArray;
  var sl:TStringList;
      i:integer;
  begin
  sl:=TStringList.Create;

  //separete delimited items by sLineBreak;TStringlist will do the job:
  sl.Text:=StringReplace(s,delimiter,sLineBreak,[rfReplaceAll]);

  //return the splitted string as an array:
  setlength(Result,sl.count);
  for i:=0 to sl.Count-1
   do Result[i]:=sl[i];

  sl.Free;
  end;



//To split a FileName (last item will be the pure filename itselfs):

 function _SplitPath(const fn:TFileName):TStringDynArray;
  begin
  result:=_SplitString(fn,'\');
  end;

*

David Ulbrich
źródło
0

W bazie odpowiedzi NGLG https://stackoverflow.com/a/8811242/6619626 możesz skorzystać z następującej funkcji:

type
OurArrayStr=array of string;

function SplitString(DelimeterChars:char;Str:string):OurArrayStr;
var
seg: TStringList;
i:integer;
ret:OurArrayStr;
begin
    seg := TStringList.Create;
    ExtractStrings([DelimeterChars],[], PChar(Str), seg);
    for i:=0 to seg.Count-1 do
    begin
         SetLength(ret,length(ret)+1);
         ret[length(ret)-1]:=seg.Strings[i];
    end;
    SplitString:=ret;
    seg.Free;
end;

Działa we wszystkich wersjach Delphi.

Reza Mousavi
źródło
0

W przypadku Delphi 2010 musisz utworzyć własną funkcję podziału.

function Split(const Texto, Delimitador: string): TStringArray;
var
  i: integer;
  Len: integer;
  PosStart: integer;
  PosDel: integer;
  TempText:string;
begin
  i := 0;
  SetLength(Result, 1);
  Len := Length(Delimitador);
  PosStart := 1;
  PosDel := Pos(Delimitador, Texto);
  TempText:=  Texto;
  while PosDel > 0 do
    begin
      Result[i] := Copy(TempText, PosStart, PosDel - PosStart);
      PosStart := PosDel + Len;
      TempText:=Copy(TempText, PosStart, Length(TempText));
      PosDel := Pos(Delimitador, TempText);
      PosStart := 1;
      inc(i);
      SetLength(Result, i + 1);
    end;
  Result[i] := Copy(TempText, PosStart, Length(TempText));
end;

Możesz odnieść się do tego jako takiego

type
  TStringArray = array of string;
var Temp2:TStringArray;
Temp1="hello:world";
Temp2=Split(Temp1,':')
user3609960
źródło
0
procedure SplitCSV(S:STRING;out SL:TStringList);
var c,commatext:string;
  a,b,up:integer;
begin
   c:=s.Replace(' ','<SPACE>');   //curate spaces

   //first ocurrence of "
   a:=pos('"',c);
   b:=pos('"',c,a+1);
   if (a>0) and (b>0) then
   begin
     commatext:=commatext+copy(c,0,a-1);
     commatext:=commatext+copy(c,a,b-a+1).Replace(',','<COMMA>');   //curate commas
     up:=b+1;
   end
   else
     commatext:=c;

   //while continue discovering "
   while (a>0) and (b>0) do
   begin
     a:=Pos('"',c,b+1);
     b:=pos('"',c,a+1);
     if (a>0) and (b>0) then
     begin
       commatext:=commatext+copy(c,up,a-up);
       commatext:=commatext+copy(c,a,b-a+1).Replace(',','<COMMA>'); //curate commas
       up:=b+1;
     end;
   end;
   //last piece of text end  
   if up<c.Length then
     commatext:=commatext+copy(c,up,c.Length-up+1);

   //split text using CommaText
   sl.CommaText:=commatext;

   sl.Text:=sl.Text.Replace('<COMMA>',',');   //curate commas
   sl.Text:=sl.Text.Replace('<SPACE>',' ');   //curate spaces
end;
Neri Bocchi
źródło
Odpowiedzi, które jasno i zwięźle wyjaśniają rozwiązanie, są o wiele bardziej przydatne niż te zawierające tylko kod.
MartynA
0
interface

uses
  Classes;

type
  TStringArray = array of string;

  TUtilStr = class
    class function Split(const AValue: string; const ADelimiter: Char = ';'; const AQuoteChar: Char = '"'): TStringArray; static;
  end;


implementation

{ TUtilStr }

class function TUtilStr.Split(const AValue: string; const ADelimiter: Char; const AQuoteChar: Char): TStringArray;
var
  LSplited: TStringList;
  LText: string;
  LIndex: Integer;
begin
  LSplited := TStringList.Create;
  try
    LSplited.StrictDelimiter := True;
    LSplited.Delimiter := ADelimiter;
    LSplited.QuoteChar := AQuoteChar;
    LSplited.DelimitedText := AValue;

    SetLength(Result, LSplited.Count);
    for LIndex := 0 to LSplited.Count - 1 do
    begin
      Result[LIndex] := LSplited[LIndex];
    end;
  finally
    LSplited.Free;
  end;
end;

end.
marvinbraga
źródło