Конференция "FreePascal" » Изобрёл велосипед (динамический массив)! [Win32]
 
  • Stargazer (25.09.05 16:49) [0]
    Привет!

    Динамический массив так, как он явлен в FPC, не совсем устраивает, ибо нужно явно указывать тип данных.
    TList, как я понял, является списком указателей, что слишком универсально, IMHO.
    Написал свой простенький инструментик для хранения нетипизированных данных - надо только указать размер элемента. Ну и приведение типов при работе с элементами массива.
    И задумался - мож, я изобрёл велосипед?

    С уважением.
  • Иван Шихалев © (26.09.05 04:31) [1]

    > Динамический массив так, как он явлен в FPC, не совсем устраивает,
    >  ибо нужно явно указывать тип данных.

    -----------------

    > надо только указать размер элемента. Ну и приведение типов
    > при работе с элементами массива.


    А разница?
  • Stargazer (26.09.05 10:05) [2]
    Разница?
    Я же не знаю размер типа, который будет храниться в массиве во время выполнения. Соответственно, встаёт проблема индексации элементов массива.

    К примеру, вот я объявляю массив:
    myarray : array of byte;


    А затем структуру
    mystruc : record
                         ...
                 end;

    mydata : mystruc;



    И как же мне запихнуть переменную mydata в массив myarray?
  • Sphinx © (26.09.05 12:12) [3]
    А разве
    myarray: array of mystruc


    нельзя ???
  • Stargazer (26.09.05 15:06) [4]

    > myarray: array of mystruc


    Можно, только в рантайме массив может "поменять" свою специализацию и хранить данные другой структуры. Поэтому неясно, как индексировать данные, тип которых на этапе компиляции неизвестен.
  • Иван Шихалев © (26.09.05 22:49) [5]

    > Можно, только в рантайме массив может "поменять" свою специализацию
    > и хранить данные другой структуры.


    Зачем?


    > Поэтому неясно, как индексировать данные, тип которых на
    > этапе компиляции неизвестен.


    Любой типизированный указатель может использоваться как массив. Индексация начинается с нуля, как и в динамических.

    var A : PInteger;

    begin
    GetMem (A, sizeof(Integer)*10);
    A[2] := 10;
    A[3] := A[2]+12;
    WriteLn (A[3])
    end

  • Stargazer (27.09.05 09:10) [6]

    > > Можно, только в рантайме массив может "поменять" свою
    > специализацию
    > > и хранить данные другой структуры.
    >
    > Зачем?


    А получается более абстрактная вещь, чем динамический массив. Удобно - потому что не нужно на каждый тип делать свой массив.
    Можно, конечно, использовать что-то вроде TList  - но меня, честно, жаба задушила на каждую вершину (или грань) свой Pointer иметь :)
    У меня есть куча разнотипных данных (вершины, грани, материалы и т.п.), которые хранятся, по сути, в однотипных массивах (хех, у них только типы элементов разные).
    Плюс в рантайме получается один загрузчик для всех этих типов - ему до лампочки, что хранить - лишь бы размер элемента был известен.


    > Любой типизированный указатель может использоваться как
    > массив. Индексация начинается с нуля, как и в динамических.
    >


    Да, это забавная штука в плане упрощения синтаксиса. И setLength не нужен уже :)
  • Иван Шихалев © (28.09.05 01:35) [7]

    > И setLength не нужен уже :)


    Только память нужно ручками выделять.
  • П7 (28.09.05 20:59) [8]
    Необязательно... Создаём массив байт, далее создаём типизированный указатель на этот массив и... (:
  • Kerk © (29.09.05 10:06) [9]
    П7   (28.09.05 20:59) [8]
    Необязательно... Создаём массив байт, далее создаём типизированный указатель на этот массив и... (:


    Так это и есть "выделение памяти".
  • Thaddy (05.10.05 23:39) [10]
    Do you mean "generics" that will be supported in .net 2? in that case it will be supported in D2007 (not yet in D2006, at least not in beta) and eventually in D2007 win32 and therefore in Freepascal 3.0 ;)
  • Sphinx © (06.10.05 08:55) [11]
    Тут наткнулся на подобный класс...
    Полностью приводить не буду - в сети он есть, достаточно скачать исходники к книге "The tomes of Delphi algorithms and data structures" - ToDADS_source.zip

    ...
     TtdRecordList = class
       private
         FActElemSize : integer;
         FArray       : PAnsiChar;
         FCount       : integer;
         FCapacity    : integer;
         FElementSize : integer;
         FIsSorted    : boolean;
         FMaxElemCount: integer;
         FName        : TtdNameString;
    ...
    {===TtdRecordList===================================================}
    constructor TtdRecordList.Create(aElementSize : integer);
    begin
     inherited Create;
     {save the actual element size}
     FActElemSize := aElementSize;
     {round the actual size to the nearest 4 bytes}
     FElementSize := ((aElementSize + 3) shr 2) shl 2;
     {calculate the maximum number of elements}
     {$IFDEF Delphi1}
     FMaxElemCount := 65535 div FElementSize;
     {$ELSE}
     FMaxElemCount := MaxInt div integer(FElementSize);
     {$ENDIF}
     FIsSorted := true;
    end;
    ...
    {--------}
    procedure TtdRecordList.Delete(aIndex : integer);
    begin
     if (aIndex < 0) or (aIndex >= Count) then
       rlError(tdeIndexOutOfBounds, 'Delete', aIndex);
     dec(FCount);
     if (aIndex < Count) then
       System.Move((FArray + (succ(aIndex) * FElementSize))^,
                   (FArray + (aIndex * FElementSize))^,
                   (Count - aIndex) * FElementSize);
     if (Count <= 1) then
       FIsSorted := true;
    end;
    ...
    {--------}
    procedure TtdRecordList.Insert(aIndex : integer; aItem : pointer);
    begin
     if (aItem = nil) then
       rlError(tdeNilItem, 'Insert', aIndex);
     if (aIndex < 0) or (aIndex > Count) then
       rlError(tdeIndexOutOfBounds, 'Insert', aIndex);
     if (Count = Capacity) then
       rlExpand;
     if (aIndex < Count) then
       System.Move((FArray + (aIndex * FElementSize))^,
                   (FArray + (succ(aIndex) * FElementSize))^,
                   (Count - aIndex) * FElementSize);
     System.Move(aItem^,
                 (FArray + (aIndex * FElementSize))^,
                 FActElemSize);
     inc(FCount);
     FIsSorted := (Count = 1);
    end;
    ...

 
Конференция "FreePascal" » Изобрёл велосипед (динамический массив)! [Win32]
Есть новые Нет новых   [134430   +0][b:0][p:0.002]