Инициализация массива Delphi

У меня в настоящее время есть это, и это сосет:

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, подобного способу, которым я хочу?

18
задан Alex O 20 February 2010 в 03:24
поделиться

3 ответа

Ответ 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, в то время как синтаксис «Создать» выше довольно новый.

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;

Возможно, вы захотите использовать ответ Джерри только для того, чтобы дать вашим массивам точек значимые имена, которые могут помочь при отладке, и одно из восьми магических чисел в этих определениях точек неверно.


Наконец, примечание о том, что имел в виду Delphi, когда говорил: «синтаксис [1, 2, 3, 4] может работать только для целых чисел». Этот синтаксис определяет набор , а не массив. У вас не может быть набора значений записей, но вы можете иметь набор целых чисел. Побочным эффектом является то, что синтаксис набора целых чисел такой же, как синтаксис открытого массива целых чисел. Я думаю, что Delphi использует контекст, чтобы выяснить, какой из них вы имеете в виду, но иногда он может угадывать неверно.

10
ответ дан 30 November 2019 в 07:12
поделиться

Массивы записей можно инциализировать в выражениях 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;
25
ответ дан 30 November 2019 в 07:12
поделиться

Вы не можете, потому что вы не можете выразить в теле кода точку так, как вы можете выразить ее в разделе 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 (или более) измерения
  • .. .но будьте осторожны, потому что это копия. :-) С сегодняшними ПК слабым местом, безусловно, будет ваша рука.:-) Вы устанете печатать гораздо быстрее, пока время копирования не будет даже замечено.

HTH

4
ответ дан 30 November 2019 в 07:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: