2010-05-01 40 views
6

Trong Delphi, người ta có thể tạo ra một loạt các loạiDelphi setlength Tuỳ chỉnh Indexing

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

đó là một loạt các yếu tố N - 1 lập chỉ mục từ 2 đến N.

Nếu chúng ta thay vì khai báo một động mảng

var 
    Arr: array of MyType 

và sau đó phân bổ N - 1 yếu tố bằng phương pháp

SetLength(Arr, N - 1) 

thì các phần tử sẽ được lập chỉ mục từ 0 đến N - 2. Có thể làm cho chúng được lập chỉ mục từ 2 đến N (nói) thay thế không?

Trả lời

15

Không, trong mảng động Delphi luôn được lập chỉ mục từ 0.

0

Điều duy nhất mà bạn có thể làm điều đó bắt chước hành vi này đang sử dụng con trỏ ..

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; 

Xin lưu ý rằng bạn bị mất bất kỳ kiểm tra phạm vi, và kết hợp điều đó với zero bắt đầu mảng không là một ý tưởng rất rất xấu !

0

Nếu bạn thực sự cần lập chỉ mục này, bạn có thể viết hàm "dịch" đơn giản, sẽ nhận được chỉ mục trong phạm vi từ 2 đến N và trả về chỉ mục từ 0 đến N-2, chỉ bằng cách trừ 2 từ tham số, ví dụ:

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

và bạn có thể gọi mảng của bạn như thế này:

array[translate(2)] 

Tất nhiên, bạn có thể bổ sung làm phạm vi kiểm tra trong phạm vi chức năng, và có lẽ bạn có thể cung cấp nó ngắn hơn.

Hoặc thậm chí tốt hơn, quấn toàn bộ quyền truy cập vào mảng với một chức năng như thế này:

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

Hope this helps

0

YES! Bằng cách sử dụng một thủ thuật!
Đầu tiên khai báo một loại mới. Tôi sử dụng một loại bản ghi thay vì một lớp vì các bản ghi dễ sử dụng hơn một chút.

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; 

Với RECORDTYPE xác định, bây giờ bạn cần phải thực hiện một chút mã:

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; 

Với kiểu được khai báo, bây giờ bạn có thể bắt đầu sử dụng nó:

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

Đó là thực sự là một thủ thuật đơn giản để tạo mảng với một phạm vi cụ thể và bạn có thể làm cho nó linh hoạt hơn nếu bạn muốn. Hoặc chuyển đổi nó thành một lớp học. Cá nhân, tôi chỉ thích các bản ghi cho các loại đơn giản này.