[delphi] 구분 기호에 따라 문자열을 문자열 배열로 분할

입력 문자열을 구분 기호를 기반으로 문자열 배열로 분할하는 Delphi 함수를 찾으려고합니다. Google에서 많은 것을 찾았지만 모두 고유 한 문제가있는 것 같고 그 중 어느 것도 작동하도록 할 수 없었습니다.

"word:doc,txt,docx"‘:’를 기반으로하는 배열로 문자열을 분할해야합니다
. 결과는입니다
['word', 'doc,txt,docx'].

작동하는 기능이있는 사람이 있습니까?

감사합니다



답변

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.


답변

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'


답변

사용할 수 있습니다 StrUtils.SplitString.

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

설명서 의 설명 :

문자열을 지정된 구분 문자로 구분 된 다른 부분으로 분할합니다.

SplitString 은 문자열을 지정된 구분 문자로 구분 된 다른 부분으로 분할합니다. S 는 분할 할 문자열입니다.
구분 기호는 구분 기호로 정의 된 문자를 포함하는 문자열입니다.

SplitString 은 원래 문자열의 분할 부분을 포함하는 System.Types.TStringDynArray 형식의 문자열 배열을 반환 합니다.


답변

Delphi XE3에 도입 된 SysUtils.TStringHelper.Split 함수 사용 :

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

이렇게하면 지정된 구분 기호가있는 문자열이 문자열 배열로 분할됩니다.


답변

나는 항상 다음과 비슷한 것을 사용합니다.

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;


답변

Mef에서 제공 하는 Explode () 함수와 비슷하지만 몇 가지 차이점이 있습니다 (그 중 하나는 버그 수정으로 간주 됨).

  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 % 구분 문자열로 구성되어 빈 요소의 배열이 생성 될 수 있습니다!)


답변

Explode는 매우 빠른 기능이며 소스는 TStrings 컴포넌트에서 가져옵니다. 폭발을 위해 다음 테스트를 사용합니다 : Explode 134217733 바이트의 데이터, 19173962 요소, 작업 시간 : 2984ms를 얻습니다.

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;