如何使用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.
答案 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没有类型的参数)。