2010-05-01 9 views
6

In Delphi ist es möglich, eine Anordnung des TypsDelphi SetLength Individuelle Indexing

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

, die ein Array von 2 bis N.

indiziert von N - 1 Elemente zu erstellen, wenn wir stattdessen eine dynamische erklären

Array
var 
    Arr: array of MyType 

zuzuteilen und später N - 1 Elemente mittels

SetLength(Arr, N - 1) 

Dann werden die Elemente von 0 bis N - 2 indiziert. Ist es möglich, sie stattdessen von 2 auf N zu indexieren?

Antwort

15

Nein, in Delphi werden dynamische Arrays immer von Null indiziert.

0

Das einzige, was Sie tun können, dass ahmt dieses Verhalten Zeiger verwendet ..

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; 

Bitte beachten Sie, dass Sie jede Bereichsprüfung verlieren, und kombinieren, die mit Nicht-Null-Start-Arrays eine sehr, sehr schlechte Idee !

0

Wenn Sie diese Indizierung wirklich benötigen, können Sie eine einfache "Übersetzungsfunktion" schreiben, die eine Indexzahl im Bereich von 2 bis N erhält und durch Subtraktion einen Index von 0 bis N-2 zurückgibt 2 aus dem Parameter, zum Beispiel:

array[translate(2)] 

natürlich könnte man zusätzlich tun Bereichsprüfung in der Funktion, und vielleicht könnten Sie geben:

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

und Sie Ihre Array wie folgt nennen könnte es ist ein kürzerer Name.

Oder noch besser, wickeln Sie den gesamten Zugriff auf das Array mit einer Funktion wie folgt aus:

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

this helps

0

YES! Mit einem Trick!
Zuerst einen neuen Typ deklarieren. Ich verwende einen Datensatztyp anstelle einer Klasse, da Datensätze ein wenig einfacher zu verwenden sind.

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; 

Mit dem Record definiert, müssen Sie jetzt ein Stück Code implementieren:

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; 

Mit dem Typ deklariert, können Sie es jetzt beginnen zu verwenden:

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

Es ist eigentlich ein einfacher Trick, um Arrays mit einem bestimmten Bereich zu erstellen, und Sie können es flexibler machen, wenn Sie möchten. Oder wandle es in eine Klasse um. Persönlich bevorzuge ich nur Datensätze für diese Arten von einfachen Typen.