Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.26;
Скачать: CL | DM;

Вниз

Вариантный массив   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.088 c
15-1162891139
Dush
2006-11-07 12:18
2006.11.26
Правильный "About"


1-1160727397
salexn
2006-10-13 12:16
2006.11.26
Использование PNG изображение в ImageList


6-1152140733
Корешь
2006-07-06 03:05
2006.11.26
icmp в indy 10


1-1161018293
Master_
2006-10-16 21:04
2006.11.26
Работа с ICL архивом иконок в Delphi


4-1152362885
Пашка
2006-07-08 16:48
2006.11.26
Как можно определить содержимое ListBox чужого процесса