แยกสตริงออกเป็นอาร์เรย์ของสตริงโดยยึดตามตัวคั่น


85

ฉันกำลังพยายามค้นหาฟังก์ชัน Delphi ที่จะแยกสตริงอินพุตออกเป็นอาร์เรย์ของสตริงตามตัวคั่น ฉันพบสิ่งต่างๆมากมายใน Google แต่ดูเหมือนจะมีปัญหาของตัวเองและฉันไม่สามารถดำเนินการใด ๆ ได้

ฉันแค่ต้องแยกสตริงเช่น: "word:doc,txt,docx"ลงในอาร์เรย์ตาม ":" ผลลัพธ์จะเป็น ['word', 'doc,txt,docx']อย่างไร

ใครมีฟังก์ชั่นที่พวกเขารู้ว่าใช้งานได้?

ขอขอบคุณ

คำตอบ:


87

คุณสามารถใช้คุณสมบัติ TStrings.DelimitedText สำหรับการแยกสตริง

ตรวจสอบตัวอย่างนี้

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.

อัปเดต

ดูนี้การเชื่อมโยงStrictDelimiterสำหรับคำอธิบายของ


22
แต่น่าเสียดายที่มีข้อผิดพลาดในหลาย ๆ "เก่า" เดลฟีรุ่น (ไม่แน่ใจซึ่งรุ่นนี้ได้คงที่) ซึ่งมีผลกระทบที่อักขระช่องว่างที่มีเสมอมาใช้เป็นตัวคั่น ดังนั้นจัดการเรื่องนี้ด้วยความระมัดระวัง !!
ลีโอ

16
ใช่. คุณจะต้องตั้งค่า StrictDelimiter เป็น true และหากคุณสมบัติ StrictDelimiter ไม่มีใน Delphi เวอร์ชันของคุณอย่าใช้เทคนิคนี้! แต่ถ้าเป็นแล้วนี่มีประโยชน์มาก
Mason Wheeler

3
ไม่ใช่ข้อผิดพลาด แต่เป็นวิธีการตัดสินใจในการออกแบบ (ที่น่ารำคาญ) ใน D1 หรือ D2 CommaText ควรจะใส่ช่องใด ๆ ที่มีช่องว่างพร้อมเครื่องหมายคำพูด หากอินพุตมีเครื่องหมายคำพูดคู่รอบฟิลด์ใด ๆ ที่มีช่องว่างผลลัพธ์จะถูกต้อง
Gerry Coll

1
สัตว์เลี้ยงตัวหนึ่งของฉันคือเมื่อผู้คนใส่ตัวบ่งชี้ประเภทในชื่อตัวแปร / พารามิเตอร์โดยไม่จำเป็น Pascal ถูกพิมพ์อย่างรุนแรง - เป็นการพิมพ์ซ้ำซ้อน (ของความหลากหลายของการออกกำลังกายนิ้ว) และทำให้เข้าใจผิดอย่างสับสนเมื่อตัวบ่งชี้ประเภทไม่ถูกต้องเช่นในกรณีนี้ ArrayOfStrings ไม่ใช่อาร์เรย์ (และด้วยเหตุนี้จึงไม่ตอบคำถามตามที่วางไว้) .
Deltics

6
สำหรับทุกคนที่โหวตคำตอบนี้โปรดทราบว่ามันไม่ได้ให้อาร์เรย์ตามที่ระบุไว้ในคำถาม ข้อกำหนดข้อกำหนดที่ไม่สมบูรณ์เป็นปัญหาใหญ่ในอุตสาหกรรมนี้การเพิกเฉยต่อข้อกำหนดที่ระบุไว้และการส่งมอบสิ่งที่ไม่ได้รับการร้องขอเป็นปัญหาใหญ่ การอนุมัติอย่างใดอย่างหนึ่งเพียงส่งเสริมการปฏิบัติที่ไม่ดี ;)
Deltics

69

ไม่จำเป็นต้องมีSplitฟังก์ชันทางวิศวกรรม Classes.ExtractStringsมันมีอยู่แล้วโปรดดูที่:

ใช้ในลักษณะต่อไปนี้:

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.

และตอบคำถามให้ครบถ้วน; Listแสดงถึงอาร์เรย์ที่ต้องการด้วยองค์ประกอบ:

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

14
ExtractStrings มีความยืดหยุ่นมาก: "การคืนค่าการขนส่งอักขระขึ้นบรรทัดใหม่และอักขระเครื่องหมายคำพูด (เดี่ยวหรือคู่) จะถือว่าเป็นตัวคั่นเสมอ"; และ "หมายเหตุ: ExtractStrings ไม่ได้เพิ่มสตริงว่างลงในรายการ"
สุดยอด

ปัญหาไม่ได้อยู่ที่การสร้างsplitฟังก์ชัน แต่เป็นความต้องการของTStringsวัตถุ และเนื่องจากความไม่ยืดหยุ่น (@awmross) กล่าวถึงฉันจึงชอบวิธีแก้ปัญหาของ Frank
Wolf

51

คุณสามารถใช้StrUtils.SplitString.

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

คำอธิบายจากเอกสารประกอบ :

แยกสตริงออกเป็นส่วนต่างๆที่คั่นด้วยอักขระตัวคั่นที่ระบุ

SplitStringแยกสตริงออกเป็นส่วนต่างๆที่คั่นด้วยอักขระตัวคั่นที่ระบุ Sคือสตริงที่จะแยก ตัวคั่นคือสตริงที่มีอักขระที่กำหนดเป็นตัวคั่น

SplitStringส่งคืนอาร์เรย์ของสตริงประเภทSystem.Types.TStringDynArrayที่มีส่วนแยกของสตริงเดิม


3
อืมไม่ใช่ใน Delphi 2010 เวอร์ชันของฉัน (มีรูทีน SplitString ใน XMLDoc และใน IdStrings (หน่วย Indy) แต่สิ่งเหล่านี้ไม่ได้ทำในสิ่งที่ผู้โพสต์ต้องการและรูทีน XMLDoc จะไม่ถูกเปิดเผยผ่านอินเทอร์เฟซหน่วยอยู่ดี)
Deltics

3
ฟังก์ชัน SplitString (const S ตัวคั่น: สตริง): TStringDynArray; กำหนดไว้ใน StrUtils.pas
alex

ฉันไม่สามารถรวมไฟล์ StrUtils.pas (แม้ว่าจะมีอยู่)
truthseeker

นี่คือตัวอย่างของการแยกสตริงออกเป็น "อาร์เรย์"
bvj

สิ่งที่ดีที่สุดคือสิ่งนี้ยอมรับตัวคั่นสตริงเมื่อเทียบกับตัวคั่นอักขระในคำตอบอื่น ๆ
user30478

42

การใช้ฟังก์ชันSysUtils.TStringHelper.Splitซึ่งแนะนำใน Delphi XE3:

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

สิ่งนี้จะแบ่งสตริงที่มีตัวคั่นที่กำหนดให้เป็นอาร์เรย์ของสตริง


19

ฉันมักจะใช้สิ่งที่คล้ายกับสิ่งนี้เสมอ:

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;

2
ทางออกที่ยอดเยี่ยมสำหรับผู้ใช้ Delphi เวอร์ชันเก่า
Wolf

ผู้ใช้ C ++ Builder 6: ฟังก์ชั่นที่เกี่ยวข้องคือStrutils::AnsiReplaceText
Wolf

เรียบง่ายอย่างน่าอัศจรรย์ ทำงานใน Delphi 7 กับ: list.Text := AnsiReplaceStr(source, delimiter, #13#10);.
AlainD

ใน Delphi 6 สามารถใช้ SysUtils.StringReplace
pyfyc

16

คล้ายกับฟังก์ชันExplode () ที่ Mef นำเสนอ แต่มีข้อแตกต่างสองสามประการ (ซึ่งหนึ่งในนั้นฉันถือว่าเป็นการแก้ไขข้อบกพร่อง):

  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;

ความแตกต่าง:

  1. พารามิเตอร์ aMax จำกัด จำนวนสตริงที่จะส่งคืน
  2. หากสตริงอินพุตถูกยกเลิกโดยตัวคั่นจะถือว่าสตริงสุดท้าย "ว่าง" ระบุมีอยู่

ตัวอย่าง:

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

มันเป็นตัวคั่นต่อท้ายและ "องค์ประกอบสุดท้ายที่ว่างเปล่า" เชิงสัญลักษณ์ที่ฉันพิจารณาแก้ไขข้อบกพร่อง

ฉันยังรวมการเปลี่ยนแปลงการจัดสรรหน่วยความจำที่ฉันแนะนำด้วยการปรับแต่ง (ฉันแนะนำผิดพลาดว่าสตริงอินพุตส่วนใหญ่อาจมีตัวคั่น 50% แต่แน่นอนว่าอาจประกอบด้วยสตริงตัวคั่น 100% ทำให้อาร์เรย์ขององค์ประกอบว่างเปล่า!)


7

Explode เป็นฟังก์ชั่นความเร็วสูงมากแหล่งที่มาได้รับจากส่วนประกอบ TStrings ฉันใช้การทดสอบถัดไปสำหรับการระเบิด: ระเบิด 134217733 ไบต์ของข้อมูลฉันได้รับองค์ประกอบ 19173962 เวลาทำงาน: 2984 ms

Implode เป็นฟังก์ชันความเร็วต่ำมาก แต่ฉันเขียนง่าย

{ ****************************************************************************** }
{  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;

3
สิ่งนี้ไม่ได้รวบรวม: Stringsไม่ใช่ประเภท
NGLN

7
var  
    su  : string;        // What we want split
    si  : TStringList;   // Result of splitting
    Delimiter : string;
    ...
    Delimiter := ';';
    si.Text := ReplaceStr(su, Delimiter, #13#10);

เส้นในรายการsiจะมีสตริงที่แยกออกมา


6

คุณสามารถสร้างฟังก์ชันของคุณเองซึ่งส่งคืน TArray ของสตริง:

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;

5

นี่คือการใช้งานฟังก์ชัน Explode ซึ่งมีอยู่ในภาษาโปรแกรมอื่น ๆ อีกมากมายเป็นฟังก์ชันมาตรฐาน:

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; 

ตัวอย่างการใช้งาน:

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

2
มีตัวเลือกที่แปลกและอาจไม่มีประสิทธิภาพอย่างมหาศาลในรหัสนี้สำหรับการจัดการ / คาดการณ์ความยาวของผลลัพธ์ เมื่อเพิ่มอาร์เรย์ผลลัพธ์ขึ้นทีละน้อยโอกาสในการจัดสรรหน่วยความจำใหม่และการแยกส่วนจะเพิ่มขึ้น มีประสิทธิภาพมากขึ้นคือการตั้งค่าความยาวเริ่มต้นให้ใหญ่ที่สุดเท่าที่จะเป็นไปได้เช่นสมมติว่าสตริงอินพุตประกอบด้วยสตริงคั่น 50% = ความยาว (S) div (2 * ความยาว (ตัวคั่น) จากนั้นตั้งค่าเป็นจำนวนจริงของ รายการเมื่อเสร็จสิ้นการจัดสรร 1 รายการตามด้วยการตัดเพียงครั้งเดียว
Deltics

นอกจากนี้คุณไม่ได้อธิบายวัตถุประสงค์ของพารามิเตอร์ Limit ฉันคาดหวังโดยสังหรณ์ใจว่าจะกำหนดจำนวนสตริงย่อยสูงสุดที่จะส่งคืนเมื่อในความเป็นจริงดูเหมือนว่าจะ จำกัด การตรวจจับสตริงย่อยไว้ที่ "ขีด จำกัด " # ตัวแรกในสตริงอินพุต สิ่งนี้ดูเหมือนไม่มีจุดหมายเนื่องจากหากคุณต้องการทำเช่นนั้นคุณก็สามารถใช้งาน Explode () ทับ Copy () ของสตริงย่อยที่ต้องการได้ การใช้ Limit เพื่อกำหนดจำนวนสตริงย่อยสูงสุดจะมีประโยชน์มากกว่า
Deltics

@ เดลติกส์: ไม่มีใครอ้างว่านี่เป็นฟังก์ชั่นที่ได้รับการปรับให้เหมาะสมอย่างมากและไม่มีใครถามหาดังนั้นฉันจึงไม่เข้าใจคำร้องเรียนของคุณ แต่บางทีคุณอาจเป็นหนึ่งในผู้ชายที่เพิ่มประสิทธิภาพทุกอย่างไม่ว่ามันจะจำเป็นหรือไม่ก็ตาม ...
ลีโอ

1
ฉันเป็นคนประเภทที่ไม่เขียนโค้ดที่ไม่มีประสิทธิภาพโดยไม่จำเป็นแล้วต้องกังวลกับการเพิ่มประสิทธิภาพในภายหลัง นี่ไม่ใช่กรณีของการวิเคราะห์โค้ดอย่างละเอียดและค้นหาศักยภาพในการเพิ่มประสิทธิภาพขนาดเล็ก แต่เป็นเพียงการขาดประสิทธิภาพที่ชัดเจนและแก้ไขได้ง่าย: การเติบโตที่เพิ่มขึ้นของหน่วยความจำที่ต่อเนื่องกันซึ่งสามารถจัดสรรไว้ล่วงหน้าได้อย่างง่ายดายและถูกตัดทอนในภายหลัง
Deltics

นอกจากนี้ @Mef: และไม่ใช่เรื่องร้องเรียน แต่เป็นความคิดเห็นข้อสังเกต แต่ที่สำคัญกว่านั้นรหัสของคุณยังมีสิ่งที่ฉันจะพิจารณาข้อบกพร่อง (ดูทางเลือกของฉันสำหรับคำอธิบาย)
Deltics

5

ฉันเขียนฟังก์ชันนี้ซึ่งส่งคืนรายการที่เชื่อมโยงของสตริงที่แยกโดยตัวคั่นเฉพาะ ปาสคาลฟรีบริสุทธิ์โดยไม่มีโมดูล

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.

3

Jedi Code Library มี StringList ที่ได้รับการปรับปรุงพร้อมฟังก์ชัน Split ในตัวซึ่งสามารถเพิ่มและแทนที่ข้อความที่มีอยู่ได้ นอกจากนี้ยังมีอินเทอร์เฟซที่นับการอ้างอิง ดังนั้นสิ่งนี้สามารถใช้ได้แม้กับ Delphi เวอร์ชันเก่าที่ไม่มี SplitStrings และการปรับแต่งสต็อก TStringList ที่ไม่ระมัดระวังและน่าเบื่อเล็กน้อยเพื่อใช้เฉพาะตัวคั่นที่ระบุ

ตัวอย่างเช่นไฟล์ข้อความของบรรทัดเช่นDog 5 4 7หนึ่งสามารถแยกวิเคราะห์โดยใช้:

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


3

วิธีนี้จะช่วยแก้ปัญหาของคุณ

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;

คุณช่วยอธิบายเกี่ยวกับการทำงานของรหัสได้หรือไม่? ขอบคุณ
Paco

มันวิ่งผ่านสตริงที่ผ่านการค้นหา const ตัวคั่นเมื่อไม่พบเชื่อมต่อกับตำแหน่งปัจจุบันบนอาร์เรย์เมื่อพบมันจะข้ามไปยังตำแหน่งถัดไปในอาร์เรย์แบบไดนามิก
Dennis

1

ฟังก์ชั่นที่ฉันชอบสำหรับการแยก:

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;

1
องค์ประกอบสุดท้ายในฟังก์ชันของคุณพลาดไป
alijunior

1
คุณต้องเพิ่มListOfStrings.add(temp);หลังลูปเพื่อเพิ่มรายการสุดท้าย
rnso

ขอบคุณสำหรับบันทึกฉันแก้ไขโค้ดในบล็อกอื่น
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;

*


0

ฐานของคำตอบ NGLG https://stackoverflow.com/a/8811242/6619626คุณสามารถใช้ฟังก์ชันต่อไปนี้:

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;

ใช้งานได้กับ Delphi ทุกรุ่น


0

สำหรับ delphi 2010 คุณต้องสร้างฟังก์ชันแยกของคุณเอง

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;

คุณสามารถอ้างถึงได้เช่นนี้

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

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;

คำตอบที่อธิบายวิธีการแก้ปัญหาอย่างชัดเจนและตรงไปตรงมามีประโยชน์มากกว่าคำตอบที่ใช้โค้ดอย่างเดียว
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.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.