Форум: "Основная";
Текущий архив: 2006.11.26;
Скачать: [xml.tar.bz2];
ВнизВариантный массив Найти похожие ветки
← →
gdaujk © (2006-10-12 10:20) [0]Доброго времени суток, уважаемые мастера.
У меня к вам следующий вопрос. Есть пустой, но уже инициализированный с помощью VarArrayCreate, двумерный вариантный массив данных типа varDouble;
V := VarArrayCreate([0, RowCount – 1, 0, ColCount - 1], varDouble);
Ещё есть обычный массив A, тоже двумерный, с тем же числом элементов. Мне необходимо скопировать массив A в вариантный массив V. Я делаю так:
for I := 0 to (RowCount - 1) do
for J := 0 to (ColCount - 1) do
V[I, J] := A[I, J];
Всё работает корректно. НО. Прочитал, что это операция заведомо очень длительная, ибо каждый раз при присвоении значения элементу V[I, J] происходит определение типа и проверка на совместимость. Предлагается подобный код:
pV := VarArrayLock(V);
Move(A, pV^, RowCount * ColCount * SizeOf(Double));
VarArrayUnlock(V);
Только этот код не работает, т. е. V не заполняется данными из A. Подскажите, что я делаю не так, и вообще, как скопировать A в V без поочерёдного приравнивания их элементов в цикле?
← →
Palladin © (2006-10-12 10:38) [1]
> gdaujk ©
массив A как объявлен?
← →
Leonid Troyanovsky © (2006-10-12 14:07) [2]
> gdaujk © (12.10.06 10:20)
> из A. Подскажите, что я делаю не так, и вообще, как скопировать
> A в V без поочерёдного приравнивания их элементов в цикле?
Взгляни на пример с одномерным массивом
http://groups.google.com/group/fido7.ru.delphi/msg/39bb6f8532669ca2
--
Regards, LVT.
← →
Сергей М. © (2006-10-12 15:25) [3]
> gdaujk © (12.10.06 10:20)
Если переменная A имеет указательный тип, то
Move(A^, .....);
← →
gdaujk © (2006-10-12 18:03) [4]>> Leonid Troyanovsky © (12.10.06 14:07) [2]
Спасибо за пример. Попробовал сделать нечто подобное для двумерного массива:TTwoDemArr = array[0..0] of array[0..0] of Double;
PTwoDemArr = ^TTwoDemArr;
procedure TForm1.Button1Click(Sender: TObject);
var
V: Variant;
A, pV: PTwoDemArr;
I, J: Integer;
begin
GetMem(A, 50 * SizeOf(Double));
for I := 0 to 9 do
for J := 0 to 4 do
A[I, J] := J * 10 + I;
V := VarArrayCreate([0, 4, 0, 9], varDouble);
pV := VarArrayLock(V);
try
Move(A^, pV^, 50 * SizeOf(Double));
finally
VarArrayUnlock(V);
end;
Label1.Caption := FloatToStr(V[0,1]);
FreeMem(A);
end;
В результате выполнения сего кода и последующего просмотра элементов V я пришёл к следующему выводу: копируется только первая строчка массива A – 0, 1, 2, … , 9 – а остальное содержимое - нет.
Замечу, что в описании функции VarArrayLock сказано: the dimensions of the returned array pointer are reversed from the dimensions of the variant array, то есть матрица превращается в обратную (может это называется по-другому, я плохо знаю математику :-)
>> Palladin © (12.10.06 10:38) [1]
Я по-всякому объявлял: и как указатель (Pointer), и как динамический двумерный массив (array of array of Double), и как описано выше. Мне кажется загвоздка не в этом…
PS: Leonid Troyanovsky, может ещё объясните вкратце суть конструкцииarray[0..0]
. Помнится, здесь я раз читал типик на эту тему, но в память ничего не осталось :-)
← →
Leonid Troyanovsky © (2006-10-12 18:54) [5]
> gdaujk © (12.10.06 18:03) [4]
> Спасибо за пример. Попробовал сделать нечто подобное для
> двумерного массива:
> TTwoDemArr = array[0..0] of array[0..0] of Double;
Не, это не совсем то. Если мы собираемся заполнить
вариант значениями массива (как потоком байтов), то
мы должны конкретно указать размерность:
TTwoDemArr = array [0..4, 0..9] of Extended;
и использовать указатель на оную структуру при чтении
этого "потока". Т.е., "принимающая" строна должна
использовать тоже описание массива, что и передающая.
В принципе же, массив любой размерности можно представить
как одномерный, используя для доступа к его элементам
(линейные) функции его индексов (и его размерностей).
См. также
http://groups.google.com/group/fido7.ru.delphi/msg/7ede8862b5ecd8b5
> PS: Leonid Troyanovsky, может ещё объясните вкратце суть
> конструкции array[0..0]. Помнится, здесь я раз читал типик
> на эту тему, но в память ничего не осталось :-)
Это не совсем верная запись.
Т.е., по-взрослому, для динамически аллоцируемых массивов
положено примерно так:
TArrayData = array [0..MAXLONGINT div 16] of Extended;
для того, чтобы можно было контролировать выход за
границу массива.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-10-12 18:59) [6]
> Leonid Troyanovsky © (12.10.06 18:54) [5]
> TTwoDemArr = array [0..4, 0..9] of Extended;
array of ... Double;
Sorry.
--
Regards, LVT.
← →
gdaujk © (2006-10-12 20:37) [7]В очередной раз убеждаюсь, что проще вместо динамических массивов использовать простые указатели. Последние мне как-то более понятны, чем
array [0..MAXLONGINT div 16]
Привожу работающий код:procedure TForm1.Button2Click(Sender: TObject);
var
V: Variant;
pV, A, p: PDouble;
I, J: Integer;
begin
GetMem(A, 50 * SizeOf(Double));
p := A;
for I := 0 to 9 do
for J := 0 to 4 do
begin
p^ := J * 10 + I;
Inc(p);
end;
V := VarArrayCreate([0, 4, 0, 9], varDouble);
pV := VarArrayLock(V);
try
Move(A^, pV^, 50 * SizeOf(Double));
finally
VarArrayUnlock(V);
end;
Label1.Caption := VarToStr(V[2,9]);
FreeMem(A);
end;
Товарищи!!! Дружно скажем "Нет!" динамическим массивам!!! :-)
PS: Leonid Troyanovsky, благодарю за идею о преобразования многомерных массивов к одномерным.
PPS: если в приведённом выше коде кто-то заметит существенные недостатки, прошу обязательно написать о них.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.11.26;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.039 c