2010-05-01 15 views
6

In Delphi, è possibile creare un array del tipoDelphi SetLength personalizzata indicizzazione

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

che è un array di elementi N - 1 indicizzati da 2 a N.

Se invece dichiara una dinamica matrice

var 
    Arr: array of MyType 

e successivamente assegnare N - 1 elementi mediante

SetLength(Arr, N - 1) 

quindi gli elementi verranno indicizzati da 0 a N - 2. È possibile renderli indicizzati da 2 a N (diciamo) invece?

risposta

15

No, negli array dinamici Delphi vengono sempre indicizzati da zero.

0

L'unica cosa che si può fare che imita questo comportamento sta usando puntatori ..

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; 

Si prega di notare che si perde alcun controllo gamma, e combinano con gli array non nulle di partenza è un MOLTO MOLTO cattiva idea !

0

Se davvero avete bisogno di questa indicizzazione, allora potreste scrivere una semplice funzione di "traduzione", che riceverà una cifra di indice nell'intervallo da 2 a N e restituirà un indice da 0 a N-2, semplicemente sottraendo 2 dal parametro, ad esempio:

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

e si potrebbe chiamare l'array come questo:

array[translate(2)] 

Naturalmente, si potrebbe inoltre fare gamma verifica all'interno della funzione, e forse si potrebbe dare è un nome più breve.

O, meglio ancora, avvolgere l'intero accesso alla matrice con una funzione come questa:

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

Spero che questo aiuti

0

SI! Usando un trucco!
Prima dichiarare un nuovo tipo. Io uso un tipo di record invece di una classe poiché i record sono un po 'più facili da usare.

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; 

Con il recordtype definito, è ora necessario per implementare un po 'di codice:

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; 

Con il tipo dichiarato, è ora possibile iniziare ad usarlo:

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

E' in realtà un semplice trucco per creare array con un intervallo specifico e puoi renderlo più flessibile se lo desideri. O convertirlo in una classe. Personalmente, preferisco solo i record per questi tipi di tipi semplici.

Problemi correlati