Pregunta

Originalmente tenía una matriz [1..1000] que se definió como una variable global. Pero ahora necesito que sea n, no 1000 y no descubro n hasta más tarde. Sé lo que es n antes de llenar la matriz, pero necesito que sea global, por lo tanto, necesito una forma de definir el tamaño de una matriz global en tiempo de ejecución.

El contexto está llenando una matriz con una transformación lineal de los bytes en un archivo. No sé qué tan grande es el archivo hasta que alguien quiera abrirlo y los archivos pueden ser de cualquier tamaño.

¿Fue útil?

Solución

A partir de Delphi 4, Delphi admite matrices dinámicas . Puede modificar sus tamaños en tiempo de ejecución y retendrán los datos que almacenó en otros elementos en el tamaño anterior. Pueden contener elementos de cualquier tipo homogéneo, incluidos registros y otras matrices. Puede declarar una matriz dinámica de la misma manera que declara normal, "estática". matrices, pero simplemente omita los límites de la matriz:

var
  ArthurArray: array of TForm;

Aunque las matrices estáticas le permiten especificar tanto el límite inferior como el superior, el índice bajo de una matriz dinámica siempre es cero. El índice alto viene dado por la función High , que siempre devuelve uno menos que la longitud de la matriz. Para cualquier matriz dinámica x , High (x) = Length (x) -1 .

Se puede acceder a una variable global mediante cualquier código, incluidos los procedimientos locales.

Una variable global de tipo de matriz dinámica se inicializará para ser una matriz vacía . Su longitud será cero y High invocado en esa matriz será -1. Low en esa matriz aún devolverá cero.

En cualquier momento, puede cambiar el tamaño de una matriz dinámica. Use la función SetLength , tal como puede hacer con las cadenas:

var
  NumElements: Integer;
begin
  NumElements := GetNumberOfArthurForms();
  SetLength(ArthurArray, NumElements);
end;

Si tiene una matriz multidimensional, puede establecer sus longitudes en un bucle:

var
  matrix: array of array of Double;
  i: Integer;
begin
  SetLength(matrix, height);
  for i := 0 to height - 1 do
    SetLength(matrix[i], width);
end;

Hay un atajo para eso para establecer las longitudes de todas las matrices internas a la vez:

begin
  SetLength(matrix, height, width);
end;

Como mencioné, las matrices dinámicas mantienen sus valores antiguos cuando los redimensiona:

var
  data: array of string;
begin
  SetLength(data, 2);
  data[1] := 'foo';
  SetLength(data, 20);
  Assert(data[1] = 'foo');
end;

Pero si acorta la matriz, los elementos que residían más allá del nuevo último elemento desaparecerán para siempre:

begin
  SetLength(data, 20);
  data[15] := 'foo';
  SetLength(data, 2);
  // data[15] does not exist anymore.
  SetLength(data, 16);
  writeln(data[15); // Should print an *empty* line.
end;

Mis demostraciones anteriores utilizaron cadenas. Las cuerdas son especiales en Delphi; son administrados por el compilador a través de recuentos de referencias. Debido a eso, los nuevos elementos de matriz dinámica de tipo cadena se inicializan para estar vacíos. Pero si hubiera usado enteros en su lugar, no habría garantía de los valores de los nuevos elementos. Pueden ser cero, pero también pueden ser cualquier otra cosa, al igual que los valores iniciales de variables locales independientes.

Me han dicho que los archivos de ayuda de Delphi 7 son muy buenos. Lea más sobre las matrices dinámicas allí. Puede encontrar demostraciones de su uso en todo el código fuente VCL y RTL proporcionado en su instalación de Delphi, así como en casi cualquier ejemplo de código de Delphi producido en los últimos 10 años.

Otros consejos

Primero, aquí hay una respuesta general a la primera parte de su pregunta:

Si su matriz ya no es estática, puede considerar usar un TList, un TStringList o una de las muchas clases de contenedor en la unidad Contnrs.

Pueden representar mejor lo que está haciendo, proporcionar capacidades adicionales que pueda necesitar, p. clasificación o pares de nombre / valor, crecen dinámicamente a medida que los necesita, y se han optimizado muy bien.


Entonces dijiste:

  

" El contexto está llenando una matriz con una transformación lineal de los bytes en un archivo. No sé qué tan grande es el archivo hasta que alguien quiera abrirlo y los archivos pueden ser de cualquier tamaño.

Para su problema específico, cargaría los bytes en un archivo usando:

  MyFileStream := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  Size := MyFileStream.Size - MyFileStream.Position;
  SetLength(Buffer, Size);
  MyFileStream.Read(Buffer[0], Size);

Entonces puede usar fácilmente un puntero PChar para recorrer cada carácter o incluso cada byte en el Buffer uno por uno y transformarlos de la manera que lo necesite.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top