Delphi SetLength 自定义索引

发布于 2024-08-30 14:57:34 字数 341 浏览 9 评论 0原文

在 Delphi 中,可以创建一个

var
  Arr: array[2..N] of MyType;

N - 1 元素组成的数组,索引从 2 到 N。

如果我们声明一个动态数组

var
  Arr: array of MyType

,然后分配 N - 1 元素,然后

SetLength(Arr, N - 1)

元素将从 0 索引到 N - 2。是否可以将它们从 2 索引到 N(比如说)?

In Delphi, it is possible to create an array of the type

var
  Arr: array[2..N] of MyType;

which is an array of N - 1 elements indexed from 2 to N.

If we instead declare a dynamic array

var
  Arr: array of MyType

and later allocate N - 1 elements by means of

SetLength(Arr, N - 1)

then the elements will be indexed from 0 to N - 2. Is it possible to make them indexed from 2 to N (say) instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

似梦非梦 2024-09-06 14:57:34

不,在 Delphi 中动态数组总是从零开始索引。

No, in Delphi dynamic arrays are always indexed from zero.

这个俗人 2024-09-06 14:57:34

是的!通过使用一个技巧!
首先声明一个新类型。我使用记录类型而不是类,因为记录更容易使用。

type
  TMyArray = record
  strict private
    FArray: array of Integer;
    FMin, FMax:Integer;
    function GetItem(Index: Integer): Integer;
    procedure SetItem(Index: Integer; const Value: Integer);
  public
    constructor Create(Min, Max: integer);
    property Item[Index: Integer]: Integer read GetItem write SetItem; Default;
    property Min: Integer read FMin;
    property Max: Integer read FMax;
  end;

定义了记录类型后,您现在需要实现一些代码:

constructor TMyArray.Create(Min, Max: integer);
begin
  FMin := Min;
  FMax := Max;
  SetLength(FArray, Max + 1 - Min);
end;

function TMyArray.GetItem(Index: Integer): Integer;
begin
  Result := FArray[Index - FMin];
end;

procedure TMyArray.SetItem(Index: Integer; const Value: Integer);
begin
  FArray[Index - FMin] := Value;
end;

声明类型后,您现在可以开始使用它:

var
  Arr: TMyArray;
begin
  Arr := TMyArray.Create(2, 10);
  Arr[2] := 10;

创建具有特定范围的数组实际上是一个简单的技巧,如果您愿意,您可以使其更加灵活。或者将其转换为类。就我个人而言,我只是更喜欢这些简单类型的记录。

YES! By using a trick!
First declare a new type. I use a record type instead of a class since records are a bit easier to use.

type
  TMyArray = record
  strict private
    FArray: array of Integer;
    FMin, FMax:Integer;
    function GetItem(Index: Integer): Integer;
    procedure SetItem(Index: Integer; const Value: Integer);
  public
    constructor Create(Min, Max: integer);
    property Item[Index: Integer]: Integer read GetItem write SetItem; Default;
    property Min: Integer read FMin;
    property Max: Integer read FMax;
  end;

With the recordtype defined, you now need to implement a bit of code:

constructor TMyArray.Create(Min, Max: integer);
begin
  FMin := Min;
  FMax := Max;
  SetLength(FArray, Max + 1 - Min);
end;

function TMyArray.GetItem(Index: Integer): Integer;
begin
  Result := FArray[Index - FMin];
end;

procedure TMyArray.SetItem(Index: Integer; const Value: Integer);
begin
  FArray[Index - FMin] := Value;
end;

With the type declared, you can now start to use it:

var
  Arr: TMyArray;
begin
  Arr := TMyArray.Create(2, 10);
  Arr[2] := 10;

It's actually a simple trick to create arrays with a specific range and you can make it more flexible if you like. Or convert it to a class. Personally, I just prefer records for these kinds of simple types.

别再吹冷风 2024-09-06 14:57:34

您唯一可以做的模仿这种行为的事情就是使用指针。

type
  TMyTypeArr = array [ 0..High(Integer) div sizeof( MyType ) - 1 ] of Mytype;
  PMyTypeArr = ^TMyTypeArr;
var
  x: ;
  A: PMyTypeArr;
begin
  SetLength( A, 2 );
  x := PMyTypeArr( @A[ 0 ] ); Dec( PMyType( x ), 2 ); // now [2,4> is valid.
  x[2] := Get_A_MyType();
end;  

请注意,您会丢失任何范围检查,并将其与非零起始数组结合起来是一个非常非常糟糕的主意!

The only thing that you can do that mimics this behaviour is using pointers..

type
  TMyTypeArr = array [ 0..High(Integer) div sizeof( MyType ) - 1 ] of Mytype;
  PMyTypeArr = ^TMyTypeArr;
var
  x: ;
  A: PMyTypeArr;
begin
  SetLength( A, 2 );
  x := PMyTypeArr( @A[ 0 ] ); Dec( PMyType( x ), 2 ); // now [2,4> is valid.
  x[2] := Get_A_MyType();
end;  

Please note that you lose any range checking, and combine that with non zero starting arrays is a VERY VERY bad idea!

泼猴你往哪里跑 2024-09-06 14:57:34

如果您确实需要这种索引,那么您可以编写一个简单的“翻译”函数,该函数将接收 2 到 N 范围内的索引数字,并返回从 0 到 N-2 的索引,只需从参数中减去 2 ,例如:

function translate(i : integer) : integer;
begin
  result := i - 2;
end;

您可以这样调用数组:

array[translate(2)]

当然,您还可以在函数内进行范围检查,也许您可​​以给它一个更短的名称。

或者甚至更好,用这样的函数包装对数组的整个访问:

function XYZ(i : integer) : MyType;
begin
  // Do range checking here...
  result := MyArray[i - 2];
end;

希望这有帮助

If you really need this indexing, then you could write a simple "translation" function, which will receive an index figure in the range from 2 to N and will return an index from 0 to N-2, just by subtracting 2 from the parameter, for example:

function translate(i : integer) : integer;
begin
  result := i - 2;
end;

And you could call your array like this:

array[translate(2)]

Of course, you could in addition do range checking within the function, and maybe you could give it a shorter name.

Or even better, wrap the whole access to the array with a function like this:

function XYZ(i : integer) : MyType;
begin
  // Do range checking here...
  result := MyArray[i - 2];
end;

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文