Delphi 数组初始化

18

我现在有这个,但它很糟糕:

type TpointArray = array [0..3] of Tpoint;

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin

  Result[0] := point(1, 1);
  Result[1] := point(1, 2);
  Result[2] := point(1, 1);
  Result[3] := point(1, 1);
end;

但是,我想做类似于这样的事情:

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin
   Result := [Point(1,1), Point(1,2), Point(1,1), Point(1,1)];
end;

然而,在编译时,它抱怨说[1,2,3,4]的语法只适用于整数。

有没有一种类似于我想要的方式来实例化/初始化Tpoint数组的方法?

3个回答

25

在const表达式中,可以初始化记录的数组:

const
  Points : TPointArray = ((X: 1; Y: 1), (X:1; Y:2), (X:1; Y:1), (X:1; Y:1));

class function rotationTable.offsets(pType, rotState, dir: integer): TpointArray;
begin
   Result := Points;
end;
在XE7中,可以通过以下方式填充记录的动态数组:
function GetPointArray: TArray<TPoint>;
begin
  Result := [Point(1,1),Point(1,2),Point(1,1),Point(1,1)];
end;

在D2006中,除非我将常量的定义更改为Points:TpointArray = ...,否则会出现“不起作用(E2010-不兼容类型)”的错误。 - yonojoy
谢谢@yonojoy - 我可能当时使用的是较新的版本。同时,我还因为使用了,而不是;而出现了语法错误。 - Gerry Coll
2
增加了一个XE7的示例,希望可以。 - LU RD

10

Plainth的答案展示了用于动态数组的类似构造函数的语法。您可以直接在TPoint数组上使用它,以生成一个更简单的帮助函数:

type
  TPointDynArray = array of TPoint;
  T4PointArray = array[0..3] of TPoint;

function PointDynArrayTo4PointArray(const input: TPointDynArray): T4PointArray;
var
  i: Integer;
begin
  Assert(Length(input) = Length(Result));
  for i := 0 to High(input) do
    Result[i] := input[i];
end;

class function rotationTable.offsets(pType, rotState, dir: integer): T4PointArray;
begin
  // New dynamic-array-constructor syntax here
  Result := PointDynArrayTo4PointArray(TPointDynArray.Create(
    Point(1,1), Point(1,2), Point(1,1), Point(1,1)));
end;

但那太过繁琐了。Delphi 也允许你在内联方式下定义开放数组,而且不需要编写额外的构造函数调用。结果使用了你最初提出的语法,但将数组包装在函数调用中。它可以在所有 Delphi 版本中使用,而上面的“Create”语法比较新。

function PointOpenArrayTo4PointArray(const input: array of TPoint): T4PointArray;
var
  i: Integer;
begin
  Assert(Length(input) = Length(Result));
  for i := 0 to High(input) do
    Result[i] := input[i];
end;

class function rotationTable.offsets(pType, rotState, dir: integer): T4PointArray;
begin
  Result := PointOpenArrayTo4PointArray(
    [Point(1,1), Point(1,2), Point(1,1), Point(1,1)]);
end;
你可能考虑使用Gerry的回答给你的点数组命名,这样有助于调试,当其中一个八个魔法数字在这些点定义中出现错误时也更容易排查。
最后,关于Delphi所说的“[1, 2, 3, 4]语法只适用于整数”的说明。该语法定义了一个集合,而不是一个数组。你不能有一个记录值的集合,但你可以有一个整数集合。副作用是整数集合的语法与整数的开放数组语法相同。我认为Delphi使用上下文来确定你想要哪一个,但有时它会猜错。

5

你不能在代码主体中以与在const部分中表达相同的方式表示一个点。

但是,您可以使用一些技巧来使生活更轻松,特别是如果您有合理数量的点。

您可以实现一个简单的过程,如下所示(未经测试的代码):

procedure BlendDimensions(aXArray, aYArray: TIntegerDynArray; var aResult: TPointArray);
var
  nCount: integer;
  i: integer;

begin
  nCount:=High(aXArray);
  if nCount <> High(aYArray) then 
    Exception.Create('The two dimension arrays must have the same number of elements!');

  SetLength(aResult, nCount);
  for i:=0 to nCount do
  begin
    aResult[i].X:=aXArray[i]; //simple copy
    aResult[i].y:=aYArray[i];
  end;
end;

...其中TIntegerDynArray是RTL的整型动态数组(实际上它可以与任何动态数组一起使用)。另外,上面例子中的TPointArray也是动态的。

因此,为了完成你的工作,你可以这样做:

procedure Foo;
var
  myXCoords, myYCoords: TIntegerDynArray; //temp arrays
  myPoints: TPointArray; //this is the real thing

begin
  myXCoords:=TIntegerDynArray.Create( 1, 2, 3, 4, 5, 6, 7, 8, 9,10);
  myYCoords:=TIntegerDynArray.Create(21,32,34,44,55,66,65,77,88,92); //...for example 
  BlendDimensions(myXCoords, myYCoords, myPoints); //build the real thing
 //use it...
end;

注意事项:

  • 您可以清楚地看到哪些是您的得分
  • 您可以以这种方式非常高效地工作
  • 您可以将BlendDimensions用于其他事物,而不仅仅是这个
  • 您可以轻松扩展BlendDimensions为3(或更多)维度
  • ……但请注意,这涉及复制。:-) 在今天的计算机上,弱点远远是你的手。:-) 您会更快地感到疲劳,直到甚至注意到复制时间。

希望对您有所帮助


我想知道这个“数组构造器”是否可以用于“记录数组”。 - Arioch 'The

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接