delphi - StrUtils.SplitString 未按预期工作

标签 delphi delphi-xe2

我使用 StrUtils 将字符串拆分为 TStringDynArray,但输出不符合预期。我将尝试解释这个问题:

我有一个字符串str:'a'; 'b'; 'c'
现在我调用 StrUtils.SplitString(str, '; '); 来拆分字符串,我期望一个包含三个元素的数组:'a''b ', 'c'

但是我得到的是一个包含五个元素的数组:'a''''b'' ''c'
当我只用 ';' 而不是 '; 进行拆分时' 我得到三个带有前导空白的元素。

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

最佳答案

此函数旨在不合并连续的分隔符。例如,考虑用逗号分割以下字符串:

foo,,bar

您希望 SplitString('foo,,bar', ',') 返回什么?您要寻找 ('foo', 'bar') 还是答案应该是 ('foo', '', 'bar')?目前尚不清楚哪个先验是正确的,并且不同的用例可能需要不同的输出。

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

'a'; 'b'

';' 处拆分,然后在 ' ' 处再次拆分。这两个分隔符之间没有任何内容,因此在 'a''b' 之间返回一个空字符串。

Split方法来自 string helper 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.

输出:

'a'
'b'
'c'

But you do not have this available to you in XE2 so I think you are going to have to roll your own split function. Which might look like this:

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;

当然,所有这些都假设您想要一个空格作为分隔符。您已在代码中要求这样做,但也许您实际上只想 ; 充当分隔符。在这种情况下,您可能希望传递 ';' 作为分隔符,并修剪返回的字符串。

关于delphi - StrUtils.SplitString 未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35840707/

相关文章:

delphi - 如何让我的控制台应用程序接收窗口消息?

delphi - 桌面 Delphi 应用程序是否可以通过 Windows 8 认证(使用 Windows 应用程序认证套件)?

delphi - 提取两个字符串之间的字符串

delphi - 在 VCL 样式表单上禁用 TButton 问题

forms - 如何锁定在 Delphi 中的克隆表单?

delphi - 用 GDI+ 替换 StretchDIBits(在将图像绘制到打印机 Canvas 时)

delphi - 在应用程序顶部绘制/覆盖一个矩形框并捕获鼠标 XY

delphi - 为什么在delphi 10.3中CopyRect翻转了第二张图像?

Delphi - Intellisense 是否会获取记录助手?

delphi - Firemonkey 网格控制 - 将列右对齐