Teilen Sie eine Zeichenfolge basierend auf einem Trennzeichen in ein Array von Zeichenfolgen auf

84

Ich versuche, eine Delphi-Funktion zu finden, die eine Eingabezeichenfolge basierend auf einem Trennzeichen in ein Array von Zeichenfolgen aufteilt. Ich habe viel bei Google gefunden, aber alle scheinen ihre eigenen Probleme zu haben, und ich konnte keine davon zum Laufen bringen.

Ich muss nur einen String wie: "word:doc,txt,docx"in ein Array teilen, das auf ':' basiert. Das Ergebnis wäre ['word', 'doc,txt,docx'].

Hat jemand eine Funktion, von der er weiß, dass sie funktioniert?

Danke dir

Ryan
quelle

Antworten:

85

Sie können die Eigenschaft TStrings.DelimitedText zum Teilen einer Zeichenfolge verwenden

Überprüfen Sie dieses Beispiel

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.

AKTUALISIEREN

Unter diesem Link finden Sie eine Erklärung von StrictDelimiter.

RRUZ
quelle
22
Leider gibt es in vielen "älteren" Delphi-Versionen einen Fehler (nicht sicher, mit welcher Version dies behoben wurde), der dazu führt, dass das Leerzeichen immer als Trennzeichen verwendet wird. Gehen Sie also vorsichtig damit um !!
Leo
16
Ja. Sie sollten StrictDelimiter auf true setzen. Wenn die StrictDelimiter-Eigenschaft in Ihrer Delphi-Version nicht verfügbar ist, verwenden Sie diese Technik nicht! Aber wenn ja, dann ist das sehr nützlich.
Mason Wheeler
3
Es war kein Fehler, es war eine (nervige) Designentscheidung in D1 oder D2. CommaText sollte alle Felder mit Leerzeichen in Anführungszeichen setzen. Wenn die Eingabe doppelte Anführungszeichen um Felder mit Leerzeichen enthält, ist das Ergebnis korrekt.
Gerry Coll
1
Eine meiner Lieblingsbeschwerden ist, wenn Leute unnötigerweise Typindikatoren in Variablen- / Parameternamen einfügen. Pascal ist stark typisiert - es ist redundantes Tippen (der Fingerübungsvariante) und verwirrend irreführend, wenn die Typanzeige falsch ist, wie in diesem Fall: ArrayOfStrings ist kein Array (und beantwortet als solches nicht einmal die gestellte Frage) .
Deltics
5
Beachten Sie für alle, die diese Antwort positiv bewerten, dass sie kein Array ergibt, wie in der Frage angegeben. Eine unvollständige Anforderungsspezifikation ist ein großes Problem in dieser Branche. Das Ignorieren der angegebenen Anforderungen und das Liefern von nicht angeforderten Anforderungen ist ein weiteres großes Problem. Die Genehmigung von beidem fördert einfach schlechte Praktiken. ;)
Deltics
67

Es ist nicht erforderlich, eine SplitFunktion zu konstruieren . Es existiert bereits, siehe : Classes.ExtractStrings.

Verwenden Sie es folgendermaßen:

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.

Und um die Frage vollständig zu beantworten; Liststellt das gewünschte Array mit den Elementen dar:

List[0] = 'word'
List[1] = 'doc,txt,docx'
NGLN
quelle
14
ExtractStrings ist sehr unflexibel: "Zeilenumbrüche, Zeilenumbrüche und Anführungszeichen (einfach oder doppelt) werden immer als Trennzeichen behandelt."; und "Hinweis: ExtractStrings fügt der Liste keine leeren Zeichenfolgen hinzu."
Awmross
Das Problem besteht nicht darin, eine splitFunktion zu konstruieren , sondern die Notwendigkeit eines TStringsObjekts. Und wegen der Erwähnungen der Inflexibilität (@awmross) würde ich Franks Lösung
Wolf
49

Sie können verwenden StrUtils.SplitString.

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

Seine Beschreibung aus der Dokumentation :

Teilt eine Zeichenfolge in verschiedene Teile auf, die durch die angegebenen Trennzeichen begrenzt sind.

SplitString teilt eine Zeichenfolge in verschiedene Teile auf, die durch die angegebenen Trennzeichen begrenzt sind. S ist die zu teilende Zeichenfolge. Trennzeichen ist eine Zeichenfolge, die die als Trennzeichen definierten Zeichen enthält.

SplitString gibt ein Array von Zeichenfolgen vom Typ System.Types.TStringDynArray zurück , das die geteilten Teile der ursprünglichen Zeichenfolge enthält.

Alex
quelle
3
Hmmm, nicht in meiner Version von Delphi 2010 (es gibt eine SplitString-Routine in XMLDoc und in (Indy-Einheit) IdStrings, aber keine von beiden macht das, was das Poster will, und die XMLDoc-Routine wird ohnehin nicht über die Einheitenschnittstelle verfügbar gemacht).
Deltics
3
Funktion SplitString (const S, Trennzeichen: Zeichenfolge): TStringDynArray; definiert in StrUtils.pas
alex
Ich kann die Datei StrUtils.pas nicht einschließen (auch wenn vorhanden).
Wahrheitssucher
Dies ist ein Beispiel für das Aufteilen eines Strings in ein "Array".
bvj
Das Beste ist, dass dies einen Zeichenfolgenbegrenzer akzeptiert, im Gegensatz zu Zeichenbegrenzern in anderen Antworten.
user30478
42

Mit Hilfe der SysUtils.TStringHelper.Split Funktion in Delphi XE3 eingeführt:

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

Dadurch wird eine Zeichenfolge mit einem bestimmten Trennzeichen in ein Array von Zeichenfolgen aufgeteilt.

LU RD
quelle
18

Ich benutze immer etwas Ähnliches:

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;
Frank
quelle
2
Tolle Lösung für Benutzer älterer Delphi-Versionen.
Wolf
C ++ Builder 6 Benutzer: Die entsprechende Funktion istStrutils::AnsiReplaceText
Wolf
Erstaunlich einfach. Arbeiten in Delphi 7 mit : list.Text := AnsiReplaceStr(source, delimiter, #13#10);.
AlainD
In Delphi 6 kann SysUtils.StringReplace
pyfyc
14

Ähnlich der von Mef angebotenen Explode () -Funktion, jedoch mit einigen Unterschieden (von denen ich einen als Fehlerbehebung betrachte):

  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;

Unterschiede:

  1. Der Parameter aMax begrenzt die Anzahl der zurückzugebenden Zeichenfolgen
  2. Wenn die Eingabezeichenfolge durch ein Trennzeichen abgeschlossen wird, gilt eine nominelle "leere" endgültige Zeichenfolge als vorhanden

Beispiele:

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

Es ist das nachfolgende Trennzeichen und das fiktive "leere letzte Element", das ich als Fehlerbehebung betrachte.

Ich habe auch die von mir vorgeschlagene Änderung der Speicherzuordnung mit Verfeinerung aufgenommen (ich habe fälschlicherweise vorgeschlagen, dass die Eingabezeichenfolge höchstens 50% Trennzeichen enthalten könnte, aber möglicherweise auch aus 100% Trennzeichen bestehen könnte, was ein Array leerer Elemente ergibt!)

Deltics
quelle
7

Explode ist eine Hochgeschwindigkeitsfunktion, deren Quellcode von der TStrings-Komponente stammt. Ich benutze den nächsten Test zum Explodieren: Explodiere 134217733 Datenbytes, ich erhalte 19173962 Elemente, Arbeitszeit: 2984 ms.

Implode ist eine sehr langsame Funktion, aber ich schreibe es einfach.

{ ****************************************************************************** }
{  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
quelle
3
Dies wird nicht kompiliert: Stringsist kein Typ.
NGLN
7
var  
    su  : string;        // What we want split
    si  : TStringList;   // Result of splitting
    Delimiter : string;
    ...
    Delimiter := ';';
    si.Text := ReplaceStr(su, Delimiter, #13#10);

Zeilen in der si- Liste enthalten geteilte Zeichenfolgen.

Ihor Konovalenko
quelle
6

Sie können Ihre eigene Funktion erstellen, die TArray of string zurückgibt:

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
quelle
5

Hier ist eine Implementierung einer Explosionsfunktion, die in vielen anderen Programmiersprachen als Standardfunktion verfügbar ist:

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; 

Beispielnutzung:

var
  res: TStringDynArray;
begin
  res := Explode(':', yourString);
Löwe
quelle
2
In diesem Code gibt es einige seltsame und möglicherweise äußerst ineffiziente Optionen zum Verwalten / Vorwegnehmen der Ergebnislänge. Durch schrittweises Erweitern des Ergebnisarrays wird die Wahrscheinlichkeit einer erneuten Zuweisung und Fragmentierung des Speichers erhöht. Effizienter wäre es, eine Anfangslänge so groß wie möglich festzulegen, dh anzunehmen, dass die Eingabezeichenfolge zu 50% aus Trennzeichen = Länge (S) div (2 * Länge (Trennzeichen) besteht. Stellen Sie sie dann auf die tatsächliche Anzahl von ein Elemente, wenn fertig. 1 Zuordnung, möglicherweise gefolgt von einer einzelnen Kürzung.
Deltics
Außerdem erklären Sie nicht den Zweck des Limit-Parameters. Ich habe intuitiv erwartet, dass es eine maximale Anzahl von Teilzeichenfolgen festlegt, die zurückgegeben werden sollen, obwohl es tatsächlich die Erkennung von Teilzeichenfolgen auf das erste "Limit" # der Zeichen in der Eingabezeichenfolge zu beschränken scheint. Dies erscheint sinnlos, da Sie bei Bedarf einfach Explode () über eine Kopie () des erforderlichen Teilstrings ausführen können. Die Verwendung von Limit zum Festlegen einer maximalen Anzahl von Teilzeichenfolgen wäre weitaus nützlicher.
Deltics
@Deltics: Niemand hat behauptet, dass dies eine hochoptimierte Funktion ist, und niemand hat nach einer gefragt, daher verstehe ich Ihre Beschwerde etwas nicht. Aber vielleicht sind Sie einer der Leute, die alles optimieren, egal ob es notwendig ist oder nicht ...
Leo
1
Ich bin der Typ, der keinen unnötig ineffizienten Code schreibt und sich später um die Optimierung kümmert. Hierbei ging es nicht darum, den Code genau zu analysieren und ein winziges Optimierungspotential zu finden, sondern lediglich um eine offensichtliche und leicht zu behebende Ineffizienz: Inkrementelles Wachstum des zusammenhängenden Speichers, das stattdessen leicht vorab zugewiesen und anschließend abgeschnitten werden kann.
Deltics
Auch @Mef: Und es war keine Beschwerde, es war ein Kommentar, eine Beobachtung. Noch wichtiger ist jedoch, dass Ihr Code auch einen Fehler enthielt (eine Erklärung finden Sie in meiner Alternative).
Deltics
5

Ich habe diese Funktion geschrieben, die eine verknüpfte Liste getrennter Zeichenfolgen nach einem bestimmten Trennzeichen zurückgibt. Reiner freier Pascal ohne Module.

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
quelle
3

Die Jedi-Codebibliothek bietet eine erweiterte StringList mit integrierter Split-Funktion, mit der der vorhandene Text sowohl hinzugefügt als auch ersetzt werden kann. Es bietet auch eine Referenzzählschnittstelle. Dies kann also auch mit älteren Delphi-Versionen verwendet werden, die keine SplitStrings haben, und ohne sorgfältige und etwas mühsame Anpassungen der Standard-TStringList, um nur bestimmte Trennzeichen zu verwenden.

Zum Beispiel kann eine gegebene Textdatei von Zeilen, wie Dog 5 4 7man sie analysieren kann, mit:

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
quelle
3

Dies wird Ihr Problem lösen

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
quelle
Können Sie bitte erklären, was der Code bewirkt? Vielen Dank
Paco
Es durchläuft die übergebene Zeichenfolge und sucht nach dem Trennzeichen const. Wenn es nicht gefunden wird, verkettet es sich mit der aktuellen Position auf dem Array. Wenn es gefunden wird, springt es zur nächsten Position im dynamischen Array
Dennis
1

Meine Lieblingsfunktion zum Teilen:

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
quelle
1
Das letzte Element wurde in Ihrer Funktion
übersehen
1
Sie müssen ListOfStrings.add(temp);nach der Schleife hinzufügen, um das letzte Element hinzuzufügen.
Rnso
Vielen Dank für den Hinweis, ich habe den Code im else-Block bearbeitet.
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
quelle
0

Die Basis der NGLG-Antwort https://stackoverflow.com/a/8811242/6619626 Sie können die folgende Funktion verwenden:

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;

Es funktioniert in allen Delphi-Versionen.

Reza Mousavi
quelle
0

Für delphi 2010 müssen Sie Ihre eigene Split-Funktion erstellen.

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;

Sie können es als solches bezeichnen

type
  TStringArray = array of string;
var Temp2:TStringArray;
Temp1="hello:world";
Temp2=Split(Temp1,':')
user3609960
quelle
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
quelle
Antworten, die die Lösung klar und prägnant erklären, sind viel nützlicher als reine Code-Antworten.
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
quelle