delphi - 如何使用 Move 连接多个字符串?

标签 delphi delphi-xe8

如何使用 Move 连接字符串数组。我尝试了这个,但我只是不知道如何让“移动”操作正常工作。

program Project2;

{$POINTERMATH ON}

procedure Concat(var S: String; const A: Array of String);
var
  I, J: Integer;
  Len: Integer;
begin
  Len := 0;
  for I := 0 to High(A) do
  Len := Len + Length(A[I]);

  SetLength(S, Length(S) + Len);

  for I := 0 to High(A) do
  Move(PWideChar(A[I])[0], S[High(S)], Length(A[I]) * SizeOf(WideChar));
end;

var
  S: String;
begin
  S := 'test';
  Concat(S, ['test', 'test2', 'test3']);
end.

最佳答案

我会像这样编写这个函数:

procedure Concat(var Dest: string; const Source: array of string);
var
  i: Integer;
  OriginalDestLen: Integer;
  SourceLen: Integer;
  TotalSourceLen: Integer;
  DestPtr: PChar;
begin
  TotalSourceLen := 0;
  OriginalDestLen := Length(Dest);
  for i := low(Source) to high(Source) do begin
    inc(TotalSourceLen, Length(Source[i]));
  end;
  SetLength(Dest, OriginalDestLen + TotalSourceLen);

  DestPtr := PChar(Pointer(Dest)) + OriginalDestLen;
  for i := low(Source) to high(Source) do begin
    SourceLen := Length(Source[i]);
    Move(Pointer(Source[i])^, DestPtr^, SourceLen*SizeOf(Char));
    inc(DestPtr, SourceLen);
  end;
end;

这是相当不言自明的。并发症是由空字符串引起的。当启用范围检查时,任何对空字符串的索引字符的尝试都会导致异常。

要处理这种复杂情况,您可以针对 Move 调用中涉及的字符串之一为空的情况添加 if 测试。我更喜欢不同的方法。我宁愿将字符串变量转换为指针。这会绕过范围检查,但也允许省略 if 语句。

Move(Pointer(Source[i])^, DestPtr^, SourceLen*SizeOf(Char));

人们可能想知道如果 Source[i] 为空会发生什么。在这种情况下,Pointer(Source[i])nil,您可能会遇到访问冲突。事实上,没有错误,因为第三个参数指定的移动长度为零,并且 nil 指针实际上从未被取消引用。

另一行注释在这里:

DestPtr := PChar(Pointer(Dest)) + OriginalDestLen;

我们使用 PChar(Pointer(Dest)) 而不是 PChar(Dest)。后者调用代码来检查 Dest 是否为空,如果是,则生成一个指向单个空终止符的指针。我们希望避免执行该代码,并直接获取 Dest 中保存的地址,即使它是 nil

关于delphi - 如何使用 Move 连接多个字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33490074/

相关文章:

delphi - 关闭线程时死锁

windows - 在 Win 7 上在桌面上画线非常慢

database - Delphi XE8 中没有 TTable 组件

delphi - 将 TSwitch 添加到每个 TListView 项目

android - TlistView OnItemClick 在 iOS 上选择第一条记录

arrays - 对数组进行排序并在Delphi中获取索引

delphi - TAlignLayout中alMostTop对齐中的 "topmost"是什么意思?

仅当应用程序处于事件状态时 Delphi FMX FormStyle StayOnTop

delphi - 如何将库路径添加到 Delphi 项目?

delphi - 如何使用 TIdTCPServer 断开不活动客户端的连接?