2010-05-01 13 views
6

En Delphi, es posible crear una matriz del tipo deDelphi SetLength Custom Indexing

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

que es una matriz de N - 1 elementos indexadas de 2 a N.

Si en lugar declaramos una dinámica array

var 
    Arr: array of MyType 

y posteriormente asignar N - 1 elementos por medio de

SetLength(Arr, N - 1) 

luego los elementos se indexarán de 0 a N - 2. ¿Es posible indexarlos de 2 a N (por ejemplo) en su lugar?

Respuesta

15

No, en Delphi las matrices dinámicas siempre están indexadas desde cero.

0

La única cosa que puede hacer que imita este comportamiento está utilizando punteros ..

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; 

Tenga en cuenta que se pierde ninguna verificación de rango, y combina eso con matrices no nulas de partida es una muy, muy mala idea !

0

Si realmente necesita esta indexación, puede escribir una función de "traducción" simple, que recibirá una cifra de índice en el rango de 2 a N y devolverá un índice de 0 a N-2, simplemente restando 2 a partir del parámetro, por ejemplo:

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

y se podría llamar la matriz de la siguiente manera:

array[translate(2)] 

por supuesto, usted podría además hacer rango de corriente dentro de la función, y tal vez usted podría dar es un nombre más corto.

O mejor aún, envuelva todo el acceso a la matriz con una función como esta:

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

Esperanza esto ayuda

0

SÍ! ¡Usando un truco!
Primero declare un nuevo tipo. Utilizo un tipo de registro en lugar de una clase, ya que los registros son un poco más fáciles de usar.

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 la RecordType definido, ahora tiene que aplicar un poco de código:

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 el tipo declarado, ahora puede empezar a utilizarlo:

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

Es en realidad es un truco simple para crear arreglos con un rango específico y puede hacerlo más flexible si lo desea. O conviértalo en una clase. Personalmente, prefiero los registros para este tipo de tipos simples.