Динамический массив любого типа

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Динамический массив любого типа

Сообщение arra » 15.07.2013 09:42:11

Доброго дня.
Сейчас пишу один проект, где много работы с динамическими массивами, в частности, много операций увеличения длины на единицу. Чтобы повысить читаемость кода решил я написать функцию, которой бы передавался по ссылке динамический массив, а она бы увеличивала его длину на единицу. Но проблема в том, что функция должна работать с массивами из любых элементов. Как это сделать, не соображу. Пробовал делать параметр функции array of variant, но тогда SetLength ругается на неправильный тип аргумента.
Подскажите, как это реализовать? Вроде простая вещь, и такой неожиданный затык.
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение vada » 15.07.2013 09:53:49

Может так сойдет?
MyDinamicArray: List<Object>;
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Динамический массив любого типа

Сообщение arra » 15.07.2013 10:56:01

Не понял, что вы имели в виду. Можно пример?
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение debi12345 » 15.07.2013 10:58:55

Сейчас пишу один проект, где много работы с динамическими массивами, в частности, много операций увеличения длины на единицу. Чтобы повысить читаемость кода решил я написать функцию, которой бы передавался по ссылке динамический массив, а она бы увеличивала его длину на единицу.

Если таких фич нужно много, то можно попробовать DECAL (аналог STL под DELPHI). приаттачено.
Вложения
decal.rar
(220.52 КБ) Скачиваний: 477
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Динамический массив любого типа

Сообщение hovadur » 15.07.2013 12:58:30

debi12345 писал(а):приаттачено.

Вероятно, это очень старая версия, которая не работает в linux, и в 64-битном режиме. Вот более новая версия https://bitbucket.org/hovadur/decal - в ней я сделал работу с linux и в 64-битах. Она работает как в windows, linux lazarus, так и в delphi 7, delphi xe2.
hovadur
постоялец
 
Сообщения: 116
Зарегистрирован: 31.01.2013 15:50:41

Re: Динамический массив любого типа

Сообщение debi12345 » 15.07.2013 13:43:12

hovadur, спасибо за ссылку !
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Динамический массив любого типа

Сообщение arra » 15.07.2013 14:00:32

Библиотеку посмотрю, спасибо.
Но в данном случае вопрос гораздо проще. Из-за такой ерунды прикручивать целую библиотеку не хочется. Должен же быть способ передавать в функцию массив из элементов любого типа! Сама SetLength же работает с любыми динамическими массивами.
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение debi12345 » 15.07.2013 14:25:13

Кажется Вы наткнулись на одну хитрую багофичу компилятора (с путаницей динамических и открытых массивоа в параметрах функций). Попробуйте следущее:
Код: Выделить всё
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.

у меня работает.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Динамический массив любого типа

Сообщение zub » 15.07.2013 14:44:36

>>Должен же быть способ передавать в функцию массив из элементов любого типа! Сама SetLength же работает с любыми динамическими массивами.
array of variant и "Динамический массив любого типа" это разные вещи.
То что SetLength работает - это внутренняя процедура компилятора, самому такую объявить не получится. SetLength кроме выделения памяти под новый эдемент должен его проинициализировать (в случае массива сложных типов), т.е. он должен знать о типе данных лежащих в массиве.
Поэтому придется написать несколько overload процедур для всех нужных типов массивов или воспользоваться генериками - готовая реализация tvector есть в пакете fpc-stl
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Динамический массив любого типа

Сообщение arra » 15.07.2013 15:22:35

Debi12345, спасибо, идея интересная. Но мне нужно не совсем это - нужно не variant массив передавать, а массив integer, Word и массив из самописных структур. Если такой массив передать в описанную тобой процедуру, она сработает? Память выделится правильно?
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение debi12345 » 15.07.2013 16:15:27

Если такой массив передать в описанную тобой процедуру, она сработает

С простыми типами работает. Сруктура как "variant" - не пробовал (подозреваю проблемы -потому что Variant-RTL делает провеки на vt-тип, ессно неизвестный для кастомных структур). Если не проканает, то придется либо работатьс массвом указателей (=возня с диманической памятью), либо массивом оф TObject (rак делает DCALC).
Или запаковать струтурный тип напрме в строку и внутри ее распарсивать. Или эмулировать RECORD в виде массива на базе "variant" (VarCreateArray, VarArrayRedim, VarArrayPut,..) - записывая в один из индексов этого массива опознавательный идентификатор структуры,а в остальные индексы - значения полей "структуры ").
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Динамический массив любого типа

Сообщение arra » 15.07.2013 16:45:03

А как работает SetLength, когда я ему отдаю массив из самописных структур? Как-то же он просекает, что ему отдали и сколько памяти выделить?
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение debi12345 » 15.07.2013 17:22:56

Вариант с засовываниеv RECORD-типа "chmorecty" в бинарный Variant-тип
(с функцией), и уже его в "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
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Динамический массив любого типа

Сообщение arra » 17.07.2013 11:01:15

Спасибо всем откликнувшимся. Но судя по всему это реализуемо гораздо сложнее, чем я думал и небольшое увеличение читаемости кода того не стоит.
arra
новенький
 
Сообщения: 27
Зарегистрирован: 30.03.2013 22:58:27

Re: Динамический массив любого типа

Сообщение debi12345 » 17.07.2013 11:28:10

Если вынести методы засовывания рекордов в массивы вариантов ("addchmo(arr: vararty; recarr: variant; var chmorec: chmorecty)" в примере) в отдельный модуль,то все будет очень просто :

Код: Выделить всё
chmorec.int_val:= 1;
    chmorec.str_val:= 'one';
      addchmo(vardata_arr,chmoarr,chmorec);


Добавлено спустя 7 минут 11 секунд:
Конкретно Ваша задача решается именно использованием VARIANT-типа.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16

Рейтинг@Mail.ru