Логическое значение по умолчанию в массиве записей - Delphi

Я помогаю своей компании со старым кодом Delphi 7.

В начале объявлена ​​запись, которая используется для хранения всех данных, которые мы хотим вывести.

тип
TOutput_Type = запись
результат: строка;
смещение результата: строка;
выбрано: логическое значение;
категория результата: целое число;
конец;

а затем объявляется массив этого

Выход: массив TOutput_Type;

В начале устанавливается большое значение длины, поскольку фактическая длина неизвестна.
Этот массив используется повсеместно, но, к сожалению, выбранное значение не всегда устанавливается при использовании.
Моя проблема в том, что я добавление сводки данных, но поскольку выбранное не установлено, delphi, кажется, присваивает ему случайный статус true или false.
Есть ли способ установить все экземпляры selected как истинные в начале? Кажется, что это достаточно просто, но я не программист Delphi, поэтому не уверен, возможно ли это? Я знаю, что могу просмотреть и добавить в selected := true каждый раз, когда создается новая запись, но я хотел бы сделать это с самого начала, если это возможно....
Заранее спасибо


person James    schedule 03.06.2010    source источник


Ответы (3)


После вызова SetLengt для выходной переменной вы должны сначала инициировать новые части записи (поскольку новая выделенная память не определена) в цикле for. Что-то типа:

OldLength := Length(Output);
SetLength(Output, NewLength);
for n := OldLength to NewLength -1 do 
  Output[n].selected := True;
person GJ.    schedule 03.06.2010
comment
Это не совсем правильно. SetLength инициализирует нулем память, которую он выделяет, что делает логические значения ложными по умолчанию. - person Ville Krumlinde; 03.06.2010
comment
Спасибо за ваше предложение; Я пробовал, и это занимает много времени. Проблема в том, что массив имеет длину 0 (чтобы очистить массив), а затем длину около 57000 :) для обработки требуется несколько минут... - person James; 03.06.2010
comment
@VilleK: Из справки Delphi: для переменной с длинной строкой или динамическим массивом SetLength перераспределяет строку или массив, на который ссылается S, до заданной длины. Существующие символы в строке или элементы в массиве сохраняются, но содержимое вновь выделенного пространства не определено. - person GJ.; 03.06.2010
comment
@James: хммм минут? Это очень долго! Обычно такой цикл с 57000 итераций занимает всего несколько мс. Можете ли вы показать свой код? - person GJ.; 03.06.2010
comment
@GJ Не уверен, что я сделал не так; после вашего комментария я скопировал ваш код и попробовал еще раз, и это было практически мгновенно :) должно быть, в первый раз я набрал что-то неправильно. Спасибо, сейчас воспользуюсь вашим предложением - person James; 03.06.2010
comment
@GJ: Также из справки Delphi: одно исключение - это увеличение длины динамического массива, в котором элементы являются типами, которые необходимо инициализировать (строки, варианты, массивы вариантов или записи, содержащие такие типы). Когда S является динамическим массивом типов, которые должны быть инициализированы, для нового выделенного пространства устанавливается значение 0 или nil. - person Ville Krumlinde; 03.06.2010
comment
@VilleK - это означает, что все строки, варианты и динамические массивы будут пустыми / нулевыми, но логические значения и целые числа будут неопределенными. Таким образом, результат и результатСмещение будут в порядке, но Selected и ResultCategory будут неопределенными. - person Gerry Coll; 04.06.2010
comment
@GJ, @Gerry: массив TOutput_Type является динамическим массивом. TOutput_Type попадает в записи, содержащие категорию таких типов, поэтому он будет обнулен. Если вы проверите подпрограмму DynArraySetLength в System.pas (которая используется при вызове SetLength), вы увидите, что она всегда очищает выделенную память с помощью вызова FillChar, по крайней мере, в Delphi 2010. Но я согласен с тем, что использование цикла для инициализации это хорошая идея, особенно в этом случае, когда желаемое значение равно True (не ноль). - person Ville Krumlinde; 04.06.2010

Записи, в отличие от объектов, не инициализируются при создании, поэтому вам нужно инициализировать их самостоятельно. Поскольку вы работаете в Delphi 7, вы не можете использовать записи с методами, поэтому я бы сделал функцию инициализации, что-то вроде этого:

type
  TOutputArray: array of TOutput_Type; 

function CreateOutputArray(length: integer): TOutputArray;
var
  i: integer;
begin
  SetLength(result, MyArbitraryItemCount);
  FillChar(result[0], Length(Output)*SizeOf(TOutput_Type), 0);
  for i := 0 to high(result) do
    result[i].selected := true;
end;
person Mason Wheeler    schedule 03.06.2010
comment
небольшая проблема с примером - вы используете длину в качестве параметра, а затем пытаетесь использовать функцию длины. Я предполагаю, что вы хотели вызвать параметр MyArbitraryItemCount - person Gerry Coll; 04.06.2010
comment
@Gerry: Да, что-то в этом роде. - person Mason Wheeler; 04.06.2010

Я бы выбрал фабричный метод, как в вопросе, связанном с dcp. Конструкторы без параметров не разрешены для записей, поэтому вам всегда придется указывать некоторые параметры, которые могут раздражать, если они вам на самом деле не нужны.

Если все дело в инициализации содержимого большого массива один раз в начале, вы также можете использовать это:

SetLength(Output, MyArbitraryItemCount);
FillChar(Output[0], Length(Output)*SizeOf(TOutput_Type), 1);

Тогда все равно 1. Включая selected :) Конечно, вы также можете использовать цикл for...

person Heinrich Ulbricht    schedule 03.06.2010
comment
Результат настройки: Строка; to Pointer($01010101) — не самая лучшая идея. - person Alex; 03.06.2010