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

时间:2015-11-03 01:43:24

标签: delphi delphi-xe8

如何使用Move连接字符串数组。我尝试了这个,但我无法想象如何让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.

2 个答案:

答案 0 :(得分:7)

我这样编写这个函数:

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;

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

要处理该复杂情况,您可以为if调用中涉及的其中一个字符串为空的情况添加Move个测试。我更喜欢不同的方法。我宁愿将字符串变量强制转换为指针。这绕过了范围检查,但也允许省略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

答案 1 :(得分:3)

在第二个循环中,您忘记S已经具有正确的大小以填充所有元素,因此您必须使用另一个变量来了解{{1}的目标参数}}

Move

source 参数转换为PWideChar是完全多余的,因为procedure Concat(var S: String; const A: Array of String); var I, Len, Sum: Integer; begin Len := 0; for I := 0 to High(A) do Inc(Len, Length(A[I])); Sum := Length(S); SetLength(S, Sum + Len); for I := 0 to High(A) do begin if Length(A[I]) > 0 then Move(A[I][1], S[Sum+1], Length(A[I]) * SizeOf(Char)); Inc(Sum, Length(A[I])); end; end; 函数使用种旧的泛型语法,允许传递您想要的所有内容(const没有类型的参数)。