Как я объявляю массив, когда я не знаю длины до времени выполнения?

Независимо от того, что вы делаете в конечном итоге, убедитесь, что вы проверяете, что ваш вход еще не был искажен magic_quotes или каким-то другим благонамеренным мусором, и, если необходимо, запустите его через stripslashes или что-то еще, чтобы его дезинфицировать .

34
задан Rob Kennedy 9 August 2013 в 17:15
поделиться

2 ответа

С Delphi 4, поддержки Delphi динамические массивы . Можно изменить их размеры во время выполнения, и они сохранят данные, которые Вы хранили в других элементах в старом размере. Они могут содержать элементы любого гомогенного типа, включая записи и другие массивы. Можно объявить динамический массив то же, поскольку Вы объявляете нормальные, "статические" массивы, но просто опускаете границы массива:

var
  ArthurArray: array of TForm;

, Хотя статические массивы позволяют Вам указывать и нижнюю и верхнюю границу, низкий индекс динамического массива всегда является нулем. Высокий индекс дан эти High функция, которая всегда возвращает тот меньше, чем длина массива. Для любого динамического массива x, High(x) = Length(x)-1.

к глобальной переменной может получить доступ любой код, включая локальные процедуры.

глобальная переменная А типа динамического массива будет инициализирована, чтобы быть пуста массив. Его длина будет нулем, и High обратился к тому массиву, будет-1. Low на том массиве все еще возвратит нуль.

В любое время, можно изменить размер динамического массива. Используйте эти SetLength функция, как можно сделать со строками:

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

, Если у Вас есть многомерный массив, можно установить их длины в цикле:

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;

существует ярлык, для которого можно установить длины всех внутренних массивов сразу:

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

Как я упомянул, динамические массивы сохраняют свои старые значения при изменении размеров их:

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

, Но если Вы сокращаетесь массив, любых элементов, которые находились вне нового последнего элемента, не стало навсегда:

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;

Мои демонстрации выше используемых строк. Строки специальны в Delphi; ими управляет компилятор посредством подсчетов ссылок. Из-за этого новые элементы динамического массива строки типа инициализируются, чтобы быть пустыми. Но если бы я использовал целые числа вместо этого, не было бы никакой гарантии значений новых элементов. Они могли бы быть нулем, но они могли бы быть чем-либо еще также точно так же, как начальные значения автономных локальных переменных.

Delphi 7 справочных файлов очень хороши, мне говорят. Читайте больше о динамических массивах там. Можно найти демонстрации их использования всюду по VCL и исходному коду RTL обеспеченными в установке Delphi, а также почти в любом примере кода Delphi произведенный за прошлые 10 лет.

93
ответ дан Rob Kennedy 27 November 2019 в 16:12
поделиться

Во-первых, вот общий ответ на первую часть Вашего вопроса:

, Если Ваш массив больше не статичен, Вы могли бы хотеть рассмотреть использование TList, TStringList или одного из многих контейнерных классов в единице Contnrs.

Они могут лучше представить то, что Вы делаете, обеспечьте дополнительные возможности, в которых Вы, возможно, нуждались бы, например, сортировка или пары имя/значение, они динамично растут, поскольку Вы нуждаетесь в них и были очень хорошо оптимизированы.

<час>

Затем Вы сказали:

"Контекст заполняет массив линейным преобразованием байтов в файле. Я не знаю, насколько большой файл - пока кто-то не хочет открыть его, и файлы могут иметь любой размер".

Для Вашей определенной проблемы, я загрузил бы байты в использовании файла:

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

Затем можно легко использовать указатель PChar, чтобы пройти каждый символ или даже каждый байт в Буфере один за другим и преобразовать их способ, которым Вы должны.

1
ответ дан lkessler 27 November 2019 в 16:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: