StrUtils.SplitString无法按预期工作

Obl*_*obl 9 delphi delphi-xe2

我使用StrUtilsin将字符串拆分为a TStringDynArray,但输出不是预期的.我会尝试解释这个问题:

我有一个字符串str:'a'; 'b'; 'c'
现在我打电话StrUtils.SplitString(str, '; ');给分割字符串和我预想的数组包含三个元素:'a','b','c'

但我得到的是有五个元素的数组:'a','','b','','c'.
当我分开';'而不是'; '我得到三个带有前导空白的元素.

那么为什么我的第一个解决方案中会出现空字符串?

Dav*_*nan 15

此功能旨在不合并连续的分隔符.例如,考虑在逗号上拆分以下字符串:

foo,,bar
Run Code Online (Sandbox Code Playgroud)

你期望什么SplitString('foo,,bar', ',')回来?你会寻找('foo', 'bar')或应该答案('foo', '', 'bar')吗?目前尚不清楚先验是否正确,不同的用例可能需要不同的输出.

如果你的情况,你指定了两个分隔符,';'' '.这意味着

'a'; 'b'
Run Code Online (Sandbox Code Playgroud)

';'和再次分裂' '.这两个分隔符之间没有什么,所以一个空字符串之间返回'a''b'.

Split从方法串助手在XE3出台了一个TStringSplitOptions参数.如果传递ExcludeEmpty该参数,则连续分隔符将被视为单个分隔符.这个程序:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

var
  S: string;

begin
  for S in '''a''; ''b''; ''c'''.Split([';', ' '], ExcludeEmpty) do begin
    Writeln(S);
  end;
end.
Run Code Online (Sandbox Code Playgroud)

输出:

'a'
'b'
'c'

但是你没有在XE2中使用它,所以我认为你将不得不推出自己的分割功能.这看起来像这样:

function IsSeparator(const C: Char; const Separators: string): Boolean;
var
  sep: Char;
begin
  for sep in Separators do begin
    if sep=C then begin
      Result := True;
      exit;
    end;
  end;
  Result := False;
end;

function Split(const Str, Separators: string): TArray<string>;
var
  CharIndex, ItemIndex: Integer;
  len: Integer;
  SeparatorCount: Integer;
  Start: Integer;
begin
  len := Length(Str);
  if len=0 then begin
    Result := nil;
    exit;
  end;

  SeparatorCount := 0;
  for CharIndex := 1 to len do begin
    if IsSeparator(Str[CharIndex], Separators) then begin
      inc(SeparatorCount);
    end;
  end;

  SetLength(Result, SeparatorCount+1); // potentially an over-allocation
  ItemIndex := 0;
  Start := 1;
  CharIndex := 1;
  for CharIndex := 1 to len do begin
    if IsSeparator(Str[CharIndex], Separators) then begin
      if CharIndex>Start then begin
        Result[ItemIndex] := Copy(Str, Start, CharIndex-Start);
        inc(ItemIndex);
      end;
      Start := CharIndex+1;
    end;
  end;

  if len>Start then begin
    Result[ItemIndex] := Copy(Str, Start, len-Start+1);
    inc(ItemIndex);
  end;

  SetLength(Result, ItemIndex);
end;
Run Code Online (Sandbox Code Playgroud)

当然,所有这些都假定您希望空间充当分隔符.您已经在代码中询问了这一点,但实际上您可能只想;充当分隔符.在这种情况下,您可能希望';'作为分隔符传递,并修剪返回的字符串.


Dal*_*kar 14

SplitString 被定义为

function SplitString(const S, Delimiters: string): TStringDynArray;
Run Code Online (Sandbox Code Playgroud)

人们会认为这Delimiters表示用于分割字符串的单个分隔符字符串,但它实际上表示用于分割字符串的单个字符集.Delimiters字符串中的每个字符都将用作可能的分隔符之一.

SplitString

将字符串分割到由指定的分隔符分隔的不同部分的字符.SplitString分割一个字符串转换成由指定的分隔符分隔的不同部分的字符.S是要拆分的字符串.分隔符是一个字符串,包含定义为分隔符的字符.


Dsm*_*Dsm 5

这是因为SplitString的第二个参数是单个字符分隔符的列表,所以'; '意味着分裂为';' 或拆分为''.所以字符串在每个';'分开 在每个空间,以及';'之间 并且''没有任何东西,因此空字符串.