Dividere una stringa in una matrice di stringhe in base a un delimitatore

Sto cercando di trovare una funzione Delphi che dividerà una stringa di input in una serie di stringhe basate su un delimitatore. Ho trovato molto su Google, ma tutti sembrano avere i loro problemi e non sono riuscito a far funzionare nessuno di loro.

Ho solo bisogno di dividere una stringa come: "word:doc,txt,docx" in un array basato su ‘:’. Il risultato sarebbe ['word', 'doc,txt,docx'] .

Qualcuno ha una funzione che sanno funzionare?

Grazie

puoi usare la proprietà TStrings.DelimitedText per dividere una stringa

controlla questo esempio

 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. 

AGGIORNARE

Vedi questo link per una spiegazione di StrictDelimiter .

Non è necessario progettare una funzione Split . Esiste già, vedi: Classes.ExtractStrings .

Usalo in un modo seguente:

 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. 

E per rispondere pienamente alla domanda; List rappresenta la matrice desiderata con gli elementi:

 List[0] = 'word' List[1] = 'doc,txt,docx' 

StrUtils.SplitString in Delphi 2010

Utilizzando la funzione SysUtils.TStringHelper.Split , introdotta in Delphi XE3:

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

Questo dividerà una stringa con un dato delimitatore in una serie di stringhe.

Simile alla funzione Explode () offerta da Mef, ma con un paio di differenze (una delle quali considero una correzione di bug):

  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; 

differenze:

  1. Il parametro aMax limita il numero di stringhe da restituire
  2. Se la stringa di input viene terminata da un separatore, viene considerata una stringa finale "vuota" nominale

Esempi:

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

È il separatore finale e "elemento finale vuoto" che considero la correzione del bug.

Ho anche incorporato il cambio di allocazione della memoria che ho suggerito, con raffinatezza (ho erroneamente suggerito che la stringa di input potrebbe al massimo contenere il 50% di separatori, ma ovviamente potrebbe consistere di stringhe di separazione al 100%, producendo una serie di elementi vuoti!)

Uso sempre qualcosa di simile a questo:

 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; 

Explode è una funzione ad altissima velocità, alhoritm di origine ottenuta dal componente TStrings. Uso il prossimo test per l’esplosione: esplodono 134217733 byte di dati, ottengo 19173962 elementi, tempo di lavoro: 2984 ms.

Implode è una funzione a velocità molto bassa, ma io la scrivo facilmente.

 { ****************************************************************************** } { 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; 
 var su : string; // What we want split si : TStringList; // Result of splitting Delimiter : string; ... Delimiter := ';'; si.Text := ReplaceStr(su, Delimiter, #13#10); 

Le righe nella lista si contengono stringhe divise.

Ecco una implementazione di una funzione di esplosione che è disponibile in molti altri linguaggi di programmazione come una funzione standard:

 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; 

Esempio di utilizzo:

 var res: TStringDynArray; begin res := Explode(':', yourString); 

Puoi creare la tua funzione che restituisce TArray di stringa:

 function mySplit(input: string): TArray; 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; 

Ho scritto questa funzione che restituisce l’elenco collegato di stringhe separate da delimitatore specifico. Pascal libero puro senza moduli.

 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. 

Jedi Code Library fornisce una StringList avanzata con funzione Split integrata, in grado sia di aggiungere che di sostituire il testo esistente. Fornisce anche un’interfaccia conteggiata di riferimento. Quindi questo può essere usato anche con versioni Delphi più vecchie che non hanno SplitStrings e senza personalizzazioni attente e un po ‘noiose di stock TStringList per usare solo delimitatori specifici.

Ad esempio, dato un file di testo di linee come Dog 5 4 7 ansible analizzarle usando:

 var slF, slR: IJclStringList; ai: TList; 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.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:[email protected]@[email protected]

Questo risolverà il tuo problema

 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; 

*

 //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; 

*

La base della risposta NGLG https://stackoverflow.com/a/8811242/6619626 è ansible utilizzare la seguente funzione:

 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; 

Funziona in tutte le versioni di Delphi.

Per Delphi 2010, è necessario creare la propria funzione di divisione.

 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; 

Puoi fare riferimento ad esso come tale

 type TStringArray = array of string; var Temp2:TStringArray; Temp1="hello:world"; Temp2=Split(Temp1,':')