Массив констант во время выполнения приложения
Автор: Peter Below
...хорошо, непосредственно это синтаксис не поддерживает, поскольку массив
констант Array of Const подобен открытым массивам, главным образом в части
характеристик времени компиляции. Но вы можете обойти этот неприятный момент,
обладая хотя бы начальными знаниями того, как реализован открытый массив. Что
нам для этого необходимо: динамически размещенный массив array of TVarRec,
который "принимает" ваши параметры, и "псевдоним" (alias) функции Format,
позволяющий работать с таким массивом без "ругани" со стороны компилятора.
type
{ объявляем тип для динамического массива array of TVarRecs }
TVarArray = array[0..High(Word) div Sizeof(TVarRec) - 1] of TVarRec;
PVarArray = ^TVarArray;
{ Объявляем alias-тип для функции Format. Передаваемые параметры будут иметь
в стеке тот же самый порядок вызова, что и при нормальном вызове Format }
FormatProxy = function(const aFormatStr: string; var aVarRec: TVarRec;
highIndex: Integer): string;
{ AddVarRecs копирует параметры, передаваемые в массиве A в pRecs^, начиная
с pRecs^[atIndex]. highIndex - самый большой доступный индекс pRecs, число
распределенных элементов - 1. }
procedure AddVarRecs(pRecs: PVarArray; atIndex, highIndex: Integer; const A:
array of const);
var
i: Integer;
begin
if pRecs <> nil then
for i := 0 to High(A) do
begin
if atIndex <= highIndex then
begin
pRecs^[atIndex] := A[i];
Inc(atIndex);
end { If }
else
Break;
end; { For }
end; { AddVarRecs }
procedure TScratchMain.SpeedButton2Click(Sender: TObject);
var
p: PVarArray;
S: string;
Proxy: FormatProxy;
begin
{ распределяем массив для четырех параметров, индексы - 0..3 }
GetMem(p, 4 * Sizeof(TVarRec));
try
{ добавляем параметры последующими вызовами AddVarRecs }
AddVarRecs(p, 0, 3, [12, 0.5, 'Шаблон']);
AddVarRecs(p, 3, 3, ['Тест']);
{ получаем полномочия Format }
@Proxy := @SysUtils.Format;
{ Вызов с динамически сгенерированным массивом параметров.
Естественно, строка формата может также быть сформирована
и во время выполнения программы. }
S := Proxy('Целое: %d, Реальное: %4.2f, Строки: %s, %s', p^[0], 3);
{ выводим результат }
ShowMessage(S);
finally
FreeMem(p, 4 * Sizeof(TVarRec));
end;
end;
|
Я надеюсь вы поняли принцип. Естественно, имеются ограничения. Вы можете
передавать в AddVarRecs числовые величины, строковые переменные и литералы, но
не в коем случае не строковые выражения! В этом случае компилятор должен для
хранения результата сформировать в стеке временную строку, передать ее в
AddVarRecs (или лучше по адресу в TVarRec), и она может прекратить свое
существование или может быть перезаписана в стеке другими данными, если в
конечном счете вы передадите в Proxy целый массив!
Тестировалось только в Delphi 1.0!
|