Move()从动态字符串数组中插入/删除项目 [英] Move() to Insert/Delete item(s) from a dynamic array of string
问题描述
使用System.Move()从字符串数组中插入/删除项目并不像从其他简单数据类型数组中插入/删除项目那样容易。问题是...在Delphi中对字符串进行引用计数。在引用计数的数据类型上使用Move()需要对内部编译器的行为有更深入的了解。
Using System.Move() to insert/delete item(s) from an array of string is not as easy as insert/delete it from other array of simple data types. The problem is ... string is reference counted in Delphi. Using Move() on reference-counted data types needs deeper knowledge on internal compiler behaviour.
这里有人可以为我解释实现此目标所需的步骤,或者通过某些方法更好代码段代码,或将我定向到互联网上的好参考书?
Can someone here explain the needed steps for me to achieve that, or better with some snippet codes, or direct me to a good reference on the internet?
哦,请不要告诉我使用懒惰但慢速的方式,
Oh, Please don't tell me to use the "lazy-but-slow way", that is, for loop, I know that.
推荐答案
我之前演示了如何从动态数组中删除项目:
I've demonstrated how to delete items from a dynamic array before:
- Delphi Q&A: How do I delete an element from an array?
在那篇文章中,我首先介绍了以下代码:
In that article, I start with the following code:
type
TXArray = array of X;
procedure DeleteX(var A: TXArray; const Index: Cardinal);
var
ALength: Cardinal;
i: Cardinal;
begin
ALength := Length(A);
Assert(ALength > 0);
Assert(Index < ALength);
for i := Index + 1 to ALength - 1 do
A[i - 1] := A[i];
SetLength(A, ALength - 1);
end;
使用该代码,您不会出错。使用所需的 X
的任何值;根据您的情况,将其替换为 string
。如果您想变得更高级并使用 Move
,那么也可以这样做。
You cannot go wrong with that code. Use whatever value for X
you want; in your case, replace it with string
. If you want to get fancier and use Move
, then there's way to do that, too.
procedure DeleteX(var A: TXArray; const Index: Cardinal);
var
ALength: Cardinal;
TailElements: Cardinal;
begin
ALength := Length(A);
Assert(ALength > 0);
Assert(Index < ALength);
Finalize(A[Index]);
TailElements := ALength - Index;
if TailElements > 0 then
Move(A[Index + 1], A[Index], SizeOf(X) * TailElements);
Initialize(A[ALength - 1]);
SetLength(A, ALength - 1);
end;
因为 X
是 string
, Finalize
调用等效于将空字符串分配给该数组元素。不过,我在此代码中使用 Finalize
,因为它适用于所有数组元素类型,甚至包括记录,接口,字符串,
Since X
is string
, the Finalize
call is equivalent to assigning the empty string to that array element. I use Finalize
in this code, though, because it will work for all array-element types, even types that include records, interfaces, strings, and other arrays.
要插入,您只需沿相反的方向移动即可。
For inserting, you just shift things the opposite direction:
procedure InsertX(var A: TXArray; const Index: Cardinal; const Value: X);
var
ALength: Cardinal;
TailElements: Cardinal;
begin
ALength := Length(A);
Assert(Index <= ALength);
SetLength(A, ALength + 1);
Finalize(A[ALength]);
TailElements := ALength - Index;
if TailElements > 0 then begin
Move(A[Index], A[Index + 1], SizeOf(X) * TailElements);
Initialize(A[Index]);
A[Index] := Value;
end;
在即将使用 Finalize
时使用执行超出语言范围的操作,例如使用非类型安全的 Move
过程覆盖编译器管理的类型的变量。重新输入语言的定义部分时,请使用初始化
。 (该语言定义了使用 SetLength
数组增长或收缩时发生的情况,但是它没有定义如何在不使用字符串分配语句的情况下复制或删除字符串。)
Use Finalize
when you're about to do something that's outside the bounds of the language, such as using the non-type-safe Move
procedure to overwrite a variable of a compiler-managed type. Use Initialize
when you're re-entering the defined part of the language. (The language defines what happens when an array grows or shrinks with SetLength
, but it doesn't define how to copy or delete strings without using a string-assignment statement.)
这篇关于Move()从动态字符串数组中插入/删除项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!