Pergunta

Eu originalmente tinha um array [1..1000] que foi definido como uma variável global. Mas agora eu preciso que seja n, não 1000 e eu não descobrir n até mais tarde. Eu sei o que n é antes de preencher a matriz, mas eu preciso dele para ser global, portanto, precisa encontrar uma maneira para definir o tamanho de uma matriz global em tempo de execução.

Contexto é o preenchimento de uma matriz com uma transformação linear dos bytes de um ficheiro. Eu não sei como grande é o arquivo até que alguém quer abri-lo e os arquivos podem ser de qualquer tamanho.

Foi útil?

Solução

A partir de Delphi 4, Delphi suportes <> fortes matrizes dinâmicas . Você pode modificar seus tamanhos em tempo de execução e eles vão manter os dados armazenados em outros elementos ao tamanho de idade. Eles podem conter elementos de qualquer tipo homogêneo, incluindo registros e outras matrizes. Você pode declarar uma matriz dinâmica a mesma que você declarar normais, matrizes "estáticas", mas simplesmente omitir os limites de matriz:

var
  ArthurArray: array of TForm;

Apesar de matrizes estáticas permitem que você especificar o limite inferior e superior, o baixo índice de uma matriz dinâmica é sempre zero. O índice elevado é dado pela função High, que sempre retorna uma menor do que o comprimento da matriz. Para qualquer x matriz dinâmica, High(x) = Length(x)-1.

Uma variável global pode ser acessado por qualquer código, incluindo os procedimentos locais.

Uma variável global de tipo matriz dinâmica será inicializado para ser um vazio array. O seu comprimento será zero e High chamado em que a matriz vai ser -1. Low nessa matriz ainda retornará zero.

A qualquer momento, você pode redimensionar uma matriz dinâmica. Use a função SetLength, assim como você pode fazer com strings:

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

Se você tem uma matriz multidimensional, você pode definir seus comprimentos em um loop:

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;

Há um atalho para isso para definir os comprimentos de todas as séries internas de uma vez:

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

Tal como já referi, matrizes dinâmicas manter seus valores antigos quando você redimensioná-las:

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

Mas se você encurtar a matriz, quaisquer elementos que residiam além da nova último elemento se foram para sempre:

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;

As minhas manifestações acima cordas usados. Cordas são especiais em Delphi; eles são gerenciados pelo compilador através de contagens de referência. Por causa disso, os novos elementos de matriz dinâmica de cadeia tipo são inicializados para estar vazio. Mas se eu tivesse usado inteiros em vez disso, não haveria garantia dos valores de novos elementos. Eles podem ser zero, mas poderia ser qualquer outra coisa, também, assim como os valores iniciais de variáveis ??locais independentes.

Os Delphi 7 arquivos de ajuda são muito bons, me disseram. Por favor, leia mais sobre matrizes dinâmicas lá. Você pode encontrar demonstrações de seu uso em todo o código VCL e RTL-fonte proporcionado na sua instalação Delphi, bem como em quase qualquer exemplo de código Delphi produzidos nos últimos 10 anos.

Outras dicas

Em primeiro lugar, aqui está uma resposta geral à primeira parte da sua pergunta:

Se o seu conjunto já não é estático, você pode querer considerar o uso de uma TList, TStringList um ou uma das muitas classes container na unidade Contnrs.

Eles podem representar melhor o que está fazendo, fornecer recursos adicionais que você pode precisar, por exemplo, classificação ou pares nome / valor, eles crescem dinamicamente à medida que você precisar deles, e foram muito bem otimizado.


Então você disse:

"Contexto é preencher uma matriz com uma transformação linear dos bytes em um arquivo. Eu não sei como grande é o arquivo até que alguém quer abri-lo e os arquivos podem ser de qualquer tamanho."

Para o seu problema específico, eu iria carregar os bytes em um arquivo usando:

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

Em seguida, você pode facilmente usar um ponteiro PChar que passar por cada personagem ou mesmo cada byte em um tampão por um e transformá-los da maneira que você precisa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top