Tách một chuỗi thành một mảng chuỗi dựa trên dấu phân cách


84

Tôi đang cố gắng tìm một hàm Delphi sẽ chia một chuỗi đầu vào thành một mảng chuỗi dựa trên dấu phân cách. Tôi đã tìm thấy rất nhiều thứ trên Google, nhưng dường như tất cả đều có vấn đề riêng và tôi không thể làm cho bất kỳ vấn đề nào trong số chúng hoạt động.

Tôi chỉ cần chia một chuỗi như: "word:doc,txt,docx"thành một mảng dựa trên ':'. Kết quả sẽ là ['word', 'doc,txt,docx'].

Có ai có chức năng mà họ biết hoạt động không?

Cảm ơn bạn

Câu trả lời:


86

bạn có thể sử dụng thuộc tính TStrings.DelimitedText để tách một chuỗi

kiểm tra mẫu này

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.

CẬP NHẬT

Xem liên kết này để giải thích về StrictDelimiter.


22
Thật không may, có một lỗi trong nhiều phiên bản Delphi "cũ" (không chắc với phiên bản này đã được sửa lỗi nào) khiến ký tự khoảng trắng luôn được sử dụng làm dấu phân cách. Vì vậy, xử lý điều này một cách cẩn thận !!
Leo

16
Vâng. Bạn sẽ muốn đặt Nghiêm cấm thành true và nếu thuộc tính Nghiêm ngặt không có sẵn trong phiên bản Delphi của bạn, đừng sử dụng kỹ thuật này! Nhưng nếu có, thì điều này rất hữu ích.
Mason Wheeler

3
Đó không phải là một lỗi, đó là một cách quyết định thiết kế (khó chịu) trong D1 hoặc D2. CommaText được cho là bao gồm bất kỳ trường nào có dấu cách với dấu ngoặc kép. Nếu đầu vào có dấu ngoặc kép xung quanh bất kỳ trường nào có dấu cách, kết quả là đúng.
Gerry Coll

1
Một trong những kẻ trộm thú cưng của tôi là khi mọi người đặt các chỉ báo kiểu vào tên biến / tham số một cách không cần thiết. Pascal được gõ mạnh - đó là cách nhập thừa (của nhiều bài tập ngón tay) và gây hiểu nhầm một cách khó hiểu khi chỉ báo kiểu sai, như trong trường hợp này: ArrayOfStrings không phải là một mảng (và như vậy thậm chí không trả lời câu hỏi như đã đặt ra) .
Deltics

6
Đối với mọi người ủng hộ câu trả lời này, xin lưu ý rằng nó không mang lại một mảng, như được chỉ định trong câu hỏi. Đặc tả yêu cầu không đầy đủ là một vấn đề lớn trong ngành này, việc bỏ qua các yêu cầu đã nêu và cung cấp một cái gì đó không được yêu cầu là một vấn đề lớn khác. Phê duyệt một trong hai chỉ đơn giản là khuyến khích thực hành xấu ;)
Deltics

67

Không cần kỹ thuật một Splitchức năng. Nó đã tồn tại, hãy xem:Classes.ExtractStrings .

Sử dụng nó theo cách sau:

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.

Và để trả lời câu hỏi một cách đầy đủ; Listđại diện cho mảng mong muốn với các phần tử:

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

14
ExtractStrings rất không linh hoạt: "Việc chuyển trả về, ký tự dòng mới và ký tự trích dẫn (đơn hoặc kép) luôn được coi là dấu phân cách."; và "Lưu ý: ExtractStrings không thêm chuỗi trống vào danh sách."
awm qua

Vấn đề không phải là thiết kế một splitchức năng, mà là nhu cầu của một TStringsđối tượng. Và vì sự cứng nhắc (@awmross) đề cập đến, tôi muốn giải pháp của Frank
Wolf

50

Bạn có thể sử dụng StrUtils.SplitString.

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

Mô tả của nó từ tài liệu :

Tách một chuỗi thành các phần khác nhau được phân tách bằng các ký tự dấu phân cách đã chỉ định.

SplitString chia một chuỗi thành các phần khác nhau được phân tách bằng các ký tự dấu phân cách đã chỉ định. S là chuỗi được chia. Dấu phân cách là một chuỗi chứa các ký tự được định nghĩa là dấu phân cách.

SplitString trả về một mảng các chuỗi kiểu System.Types.TStringDynArray chứa các phần được tách của chuỗi ban đầu.


3
Rất tiếc, không có trong phiên bản Delphi 2010 của tôi (có quy trình SplitString trong XMLDoc và trong IdStrings (đơn vị Indy), nhưng cả hai đều không làm những gì người đăng muốn và quy trình XMLDoc không được hiển thị thông qua giao diện đơn vị).
Deltics

3
function SplitString (const S, Delimiters: string): TStringDynArray; được định nghĩa trong StrUtils.pas
alex

Tôi không thể bao gồm tệp StrUtils.pas (ngay cả khi có).
truthseeker

Đây là một ví dụ về tách một chuỗi thành một "mảng".
bvj

điều tốt nhất là điều này chấp nhận một dấu phân cách chuỗi trái ngược với dấu phân cách char trong các câu trả lời khác.
user30478

42

Sử dụng hàm SysUtils.TStringHelper.Split , được giới thiệu trong Delphi XE3:

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

Thao tác này sẽ chia một chuỗi có dấu phân cách đã cho thành một mảng chuỗi.


18

Tôi luôn sử dụng một cái gì đó tương tự như thế này:

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
Giải pháp tuyệt vời cho người dùng các phiên bản Delphi cũ hơn.
Wolf,

C ++ Builder 6 người sử dụng: các chức năng tương ứng làStrutils::AnsiReplaceText
Wolf

Đơn giản đến kinh ngạc. Làm việc trong Delphi 7 với: list.Text := AnsiReplaceStr(source, delimiter, #13#10);.
AlainD

Trong Delphi 6 có thể sử dụng SysUtils.StringReplace
pyfyc

14

Tương tự như hàm Explode () do Mef cung cấp, nhưng có một vài điểm khác biệt (một trong số đó tôi coi là một bản sửa lỗi):

  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;

Sự khác biệt:

  1. Tham số aMax giới hạn số lượng chuỗi được trả về
  2. Nếu chuỗi đầu vào được kết thúc bằng dấu phân tách thì chuỗi cuối cùng "trống" danh nghĩa được coi là tồn tại

Ví dụ:

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

Đó là dấu phân cách theo sau và "phần tử cuối cùng trống" mà tôi coi là bản sửa lỗi.

Tôi cũng kết hợp thay đổi phân bổ bộ nhớ mà tôi đã đề xuất, với sự tinh chỉnh (tôi đã nhầm lẫn khi đề xuất chuỗi đầu vào có thể chứa nhiều nhất 50% dấu phân tách, nhưng có thể hình dung nó tất nhiên bao gồm 100% chuỗi dấu phân cách, tạo ra một mảng các phần tử trống!)


7

Explode là chức năng tốc độ rất cao, nguồn alhoritm lấy từ thành phần TStrings. Tôi sử dụng thử nghiệm tiếp theo để phát nổ: Explode 134217733 byte dữ liệu, tôi nhận được 19173962 phần tử, thời gian làm việc: 2984 ms.

Implode là chức năng tốc độ rất thấp, nhưng tôi viết nó dễ dàng.

{ ****************************************************************************** }
{  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
Điều này không biên dịch: Stringskhông phải là một kiểu.
NGLN

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

Các dòng trong danh sách si sẽ chứa các chuỗi được chia nhỏ.


6

Bạn có thể tạo hàm của riêng mình để trả về TArray của chuỗi:

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

Đây là một triển khai của một hàm bùng nổ có sẵn trong nhiều ngôn ngữ lập trình khác như một hàm tiêu chuẩn:

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; 

Sử dụng mẫu:

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

2
Có một số lựa chọn kỳ lạ và có khả năng cực kỳ kém hiệu quả trong mã này để quản lý / dự đoán độ dài của kết quả. Bằng cách tăng dần mảng kết quả, cơ hội phân bổ lại bộ nhớ và phân mảnh được tăng lên. Hiệu quả hơn sẽ là đặt độ dài ban đầu lớn nhất có thể, tức là giả sử rằng chuỗi đầu vào bao gồm 50% chuỗi phân tách = Độ dài (S) div (2 * Độ dài (Dấu phân cách). Sau đó đặt nó thành số thực tế là các mục khi được hoàn thành. 1 lần phân bổ có khả năng bị cắt bớt một lần.
Deltics

Ngoài ra, bạn không giải thích mục đích của tham số Giới hạn. Theo trực giác, tôi mong đợi nó đặt số lượng chuỗi con tối đa được trả về trong khi trên thực tế, nó dường như hạn chế việc phát hiện các chuỗi con đối với số ký tự "Giới hạn" đầu tiên trong chuỗi đầu vào. Điều này có vẻ vô nghĩa vì nếu bạn cần làm điều đó, bạn có thể chỉ cần vận hành Explode () trên Bản sao () của chuỗi con được yêu cầu. Sử dụng Giới hạn để đặt số lượng chuỗi con tối đa sẽ hữu ích hơn nhiều.
Deltics

@Deltics: Không ai tuyên bố rằng đây là một chức năng được tối ưu hóa cao và cũng không ai yêu cầu một chức năng này, vì vậy tôi hơi không hiểu khiếu nại của bạn. Nhưng có lẽ bạn là một trong những người tối ưu hóa mọi thứ, bất kể điều đó có cần thiết hay không ...
Leo

1
Tôi là loại người không viết mã không hiệu quả một cách cần thiết, sau đó lo lắng về việc tối ưu hóa sau này. Đây không phải là trường hợp phân tích mã một cách chi tiết và tìm ra một số tiềm năng tối ưu hóa nhỏ, nó chỉ đơn giản là một sự thiếu hiệu quả rõ ràng và dễ giải quyết: Sự phát triển ngày càng tăng của bộ nhớ liền kề mà thay vào đó có thể dễ dàng được cấp phát trước và sau đó bị cắt bớt.
Deltics

Ngoài ra @Mef: Và đó không phải là một lời phàn nàn, đó là một nhận xét, một quan sát. Nhưng quan trọng hơn, mã của bạn cũng chứa những gì tôi sẽ coi là một lỗi (xem giải thích thay thế của tôi).
Deltics

5

Tôi đã viết hàm này trả về danh sách liên kết của các chuỗi được phân tách bằng dấu phân cách cụ thể. Pascal miễn phí thuần túy không có mô-đun.

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

Thư viện mã Jedi cung cấp một StringList nâng cao với chức năng Split được tích hợp sẵn, có khả năng thêm và thay thế văn bản hiện có. Nó cũng cung cấp giao diện được tính tham chiếu. Vì vậy, điều này có thể được sử dụng ngay cả với các phiên bản Delphi cũ hơn không có SplitStrings và không có các tùy chỉnh cẩn thận và tẻ nhạt của TStringList cổ phiếu để chỉ sử dụng các dấu phân cách được chỉ định.

Ví dụ: tệp văn bản đã cho của các dòng như thế này Dog 5 4 7có thể phân tích cú pháp chúng bằng cách sử dụng:

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

Điều này sẽ giải quyết vấn đề của bạn

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;

Bạn có thể vui lòng cho một số giải thích về những gì mã làm được không? Cảm ơn
Paco

nó chạy qua chuỗi thông qua tìm kiếm các const delimiter, khi không tìm thấy, concatenate với vị trí hiện tại trên mảng, khi sáng lập, nhảy lên vị trí tiếp theo trong mảng động
Dennis

1

Chức năng yêu thích của tôi để tách:

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
Yếu tố cuối cùng đã bỏ lỡ trong chức năng của bạn
alijunior

1
Bạn cần thêm ListOfStrings.add(temp);vào sau vòng lặp để thêm mục cuối cùng.
rnso

Cảm ơn vì ghi chú, tôi đã chỉnh sửa mã trong khối khác.
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

Cơ sở của câu trả lời NGLG https://stackoverflow.com/a/8811242/6619626 bạn có thể sử dụng chức năng sau:

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;

Nó hoạt động trong tất cả các phiên bản Delphi.


0

Đối với delphi 2010, bạn cần tạo chức năng phân chia của riêng mình.

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;

Bạn có thể tham khảo nó như vậy

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;

Các câu trả lời giải thích giải pháp rõ ràng và thành công sẽ hữu ích hơn nhiều so với những câu chỉ có mã.
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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.