Динамический массив любого типа
Модератор: Модераторы
Динамический массив любого типа
Доброго дня.
Сейчас пишу один проект, где много работы с динамическими массивами, в частности, много операций увеличения длины на единицу. Чтобы повысить читаемость кода решил я написать функцию, которой бы передавался по ссылке динамический массив, а она бы увеличивала его длину на единицу. Но проблема в том, что функция должна работать с массивами из любых элементов. Как это сделать, не соображу. Пробовал делать параметр функции array of variant, но тогда SetLength ругается на неправильный тип аргумента.
Подскажите, как это реализовать? Вроде простая вещь, и такой неожиданный затык.
Сейчас пишу один проект, где много работы с динамическими массивами, в частности, много операций увеличения длины на единицу. Чтобы повысить читаемость кода решил я написать функцию, которой бы передавался по ссылке динамический массив, а она бы увеличивала его длину на единицу. Но проблема в том, что функция должна работать с массивами из любых элементов. Как это сделать, не соображу. Пробовал делать параметр функции array of variant, но тогда SetLength ругается на неправильный тип аргумента.
Подскажите, как это реализовать? Вроде простая вещь, и такой неожиданный затык.
Может так сойдет?
MyDinamicArray: List<Object>;
MyDinamicArray: List<Object>;
Не понял, что вы имели в виду. Можно пример?
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Сейчас пишу один проект, где много работы с динамическими массивами, в частности, много операций увеличения длины на единицу. Чтобы повысить читаемость кода решил я написать функцию, которой бы передавался по ссылке динамический массив, а она бы увеличивала его длину на единицу.
Если таких фич нужно много, то можно попробовать DECAL (аналог STL под DELPHI). приаттачено.
- Вложения
-
- decal.rar
- (220.52 КБ) 559 скачиваний
debi12345 писал(а):приаттачено.
Вероятно, это очень старая версия, которая не работает в linux, и в 64-битном режиме. Вот более новая версия https://bitbucket.org/hovadur/decal - в ней я сделал работу с linux и в 64-битах. Она работает как в windows, linux lazarus, так и в delphi 7, delphi xe2.
Библиотеку посмотрю, спасибо.
Но в данном случае вопрос гораздо проще. Из-за такой ерунды прикручивать целую библиотеку не хочется. Должен же быть способ передавать в функцию массив из элементов любого типа! Сама SetLength же работает с любыми динамическими массивами.
Но в данном случае вопрос гораздо проще. Из-за такой ерунды прикручивать целую библиотеку не хочется. Должен же быть способ передавать в функцию массив из элементов любого типа! Сама SetLength же работает с любыми динамическими массивами.
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Кажется Вы наткнулись на одну хитрую багофичу компилятора (с путаницей динамических и открытых массивоа в параметрах функций). Попробуйте следущее:
у меня работает.
Код: Выделить всё
program test;
{$mode objfpc}
uses
variants;
type
vararty = array of variant;
procedure addelem(var arr: vararty; elem: variant);
begin
setlength(arr,length(arr)+1);
arr[high(arr)] := elem;
end;
var
a1: vararty;
begin
addelem(a1,2);
addelem(a1,1.23);
addelem(a1,'test');
end.
у меня работает.
>>Должен же быть способ передавать в функцию массив из элементов любого типа! Сама SetLength же работает с любыми динамическими массивами.
array of variant и "Динамический массив любого типа" это разные вещи.
То что SetLength работает - это внутренняя процедура компилятора, самому такую объявить не получится. SetLength кроме выделения памяти под новый эдемент должен его проинициализировать (в случае массива сложных типов), т.е. он должен знать о типе данных лежащих в массиве.
Поэтому придется написать несколько overload процедур для всех нужных типов массивов или воспользоваться генериками - готовая реализация tvector есть в пакете fpc-stl
array of variant и "Динамический массив любого типа" это разные вещи.
То что SetLength работает - это внутренняя процедура компилятора, самому такую объявить не получится. SetLength кроме выделения памяти под новый эдемент должен его проинициализировать (в случае массива сложных типов), т.е. он должен знать о типе данных лежащих в массиве.
Поэтому придется написать несколько overload процедур для всех нужных типов массивов или воспользоваться генериками - готовая реализация tvector есть в пакете fpc-stl
Debi12345, спасибо, идея интересная. Но мне нужно не совсем это - нужно не variant массив передавать, а массив integer, Word и массив из самописных структур. Если такой массив передать в описанную тобой процедуру, она сработает? Память выделится правильно?
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Если такой массив передать в описанную тобой процедуру, она сработает
С простыми типами работает. Сруктура как "variant" - не пробовал (подозреваю проблемы -потому что Variant-RTL делает провеки на vt-тип, ессно неизвестный для кастомных структур). Если не проканает, то придется либо работатьс массвом указателей (=возня с диманической памятью), либо массивом оф TObject (rак делает DCALC).
Или запаковать струтурный тип напрме в строку и внутри ее распарсивать. Или эмулировать RECORD в виде массива на базе "variant" (VarCreateArray, VarArrayRedim, VarArrayPut,..) - записывая в один из индексов этого массива опознавательный идентификатор структуры,а в остальные индексы - значения полей "структуры ").
А как работает SetLength, когда я ему отдаю массив из самописных структур? Как-то же он просекает, что ему отдали и сколько памяти выделить?
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Вариант с засовываниеv RECORD-типа "chmorecty" в бинарный Variant-тип
(с функцией), и уже его в "vararty = array of variant " :
Добавлено спустя 2 часа 57 минут 12 секунд:
(с функцией), и уже его в "vararty = array of variant " :
Код: Выделить всё
program test;
{$mode objfpc}{$h+}
uses
variants,sysutils;
type
vararty = array of variant;
chmorecty = packed record
int_val: integer;
str_val: shortstring;
end;
pchmorecty = ^chmorecty;
procedure addelem(var arr: vararty; elem: variant);
begin
if VarIsArray(elem) then begin
with pchmorecty(VarArrayLock(elem))^ do begin
writeln('added record: {' + inttostr(int_val) + ',' + str_val +'}');
VarArrayUnlock(elem);
end;
end else begin
writeln('added atomic: ' + varToStr(elem));
end;
setlength(arr,length(arr)+1);
arr[high(arr)] := elem;
end;
procedure addchmo(arr: vararty; recarr: variant; var chmorec: chmorecty);
var
chmorecptr: pchmorecty;
sz: integer;
begin
sz:= sizeof(chmorecty);
chmorecptr := VarArrayLock(recarr);
Move(chmorec,chmorecptr^,sz);
VarArrayUnlock(recarr);
addelem(arr,recarr);
end;
var
vardata_arr: vararty;
chmoarr: variant;
chmorec: chmorecty;
begin
chmoarr:= vararraycreate([0,sizeof(chmorecty)],varByte);
addelem(vardata_arr,2);
addelem(vardata_arr,1.23);
addelem(vardata_arr,'test');
chmorec.int_val:= 1;
chmorec.str_val:= 'one';
addchmo(vardata_arr,chmoarr,chmorec);
chmorec.int_val:= 100;
chmorec.str_val:= 'hundred';
addchmo(vardata_arr,chmoarr,chmorec);
varclear(chmoarr);
end.
Добавлено спустя 2 часа 57 минут 12 секунд:
Потому что они одинаковые = можно точно узнать/предсказать/выделить размер и количесово.А как работает SetLength, когда я ему отдаю массив из самописных структур? Как-то же он просекает, что ему отдали и сколько памяти выделить?
Спасибо всем откликнувшимся. Но судя по всему это реализуемо гораздо сложнее, чем я думал и небольшое увеличение читаемости кода того не стоит.
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Если вынести методы засовывания рекордов в массивы вариантов ("addchmo(arr: vararty; recarr: variant; var chmorec: chmorecty)" в примере) в отдельный модуль,то все будет очень просто :
Добавлено спустя 7 минут 11 секунд:
Конкретно Ваша задача решается именно использованием VARIANT-типа.
Код: Выделить всё
chmorec.int_val:= 1;
chmorec.str_val:= 'one';
addchmo(vardata_arr,chmoarr,chmorec);Добавлено спустя 7 минут 11 секунд:
Конкретно Ваша задача решается именно использованием VARIANT-типа.
