Ада: изменение длины массива при добавлении нового элемента

Я пытаюсь создать пакет динамического массива. У меня есть универсальный пакет с универсальным типом, а затем я объявил в .ads массив (положительные индексы) элементов Elem_Type. Мне было любопытно, можно ли создать процедуру Append(Vector, Item), где изменить длину вектора, позволяя ему взять еще один элемент. Что-то вроде того, когда у вас есть буфер[100] в C, и вы выделяете ему еще 1 элемент, чтобы сделать его 101, а затем добавляете что-то в позицию 101.

Я не знаю никакого Ада, но обратите внимание, что в C функция realloc() часто просто выделяет новый массив большего размера, копирует содержимое старого и возвращает новый. Предположительно, вы можете реализовать это в Аде.

Ernest Friedman-Hill 27.05.2019 17:22

Если вы делаете это из академического интереса, хорошо; см. Ответ Джере. Если нет, найдите Ада.Контейнеры.Векторы.

Simon Wright 27.05.2019 18:47

... или, если переносимость компилятора не имеет значения, взгляните на GNAT.Table или GNAT.Dynamic_Tables (в GPS см. "Справка > GNAT Runtime > GNAT > (Динамическая) таблица"). Эти структуры данных также используются внутри GNAT (см., например, здесь).

DeeDee 27.05.2019 20:48
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
4
3
612
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В Аде общий способ сделать это — создать новый блок большего размера, затем скопировать в него содержимое и освободить старый блок. Я часто предлагаю выделять новые блоки кратно некоторому большому размеру фрагмента, чтобы вам не приходилось много перераспределять. Например, если вам нужно выделить новый массив, вместо добавления одного дополнительного элемента добавьте 500 (или какое-то число, которое имеет смысл).

Обратите внимание, что даже в C функция realloc() часто делает именно это. В нетривиальных проектах не принято, чтобы функция realloc() могла просто добавить еще один элемент. Часто приходится создавать целый новый массив и выполнять его копирование, как я предлагаю для Ады.

Некоторые другие варианты в Ada включают создание собственного пула хранения, который значительно упрощает и ускоряет перераспределение, но вам нужно придумать алгоритм, как это сделать, или найти кого-то еще. Вы также можете делать привязки к функциям C, но вы не можете смешивать malloc/realloc/free с new/unchecked_deallocation в Аде.

похоже, вы хотите использовать общий пакет Ada.Containers.Vectors или, возможно, пакет Ada.Containers.Indefinite_Vectors. Эти пакеты уже определяют все возможности, которые вам кажутся необходимыми. Описание универсального пакета Ada.Containers.Vectors, как показано в Ада 2012 Справочное руководство,

with Ada.Iterator_Interfaces;
generic
   type Index_Type is range <>;
   type Element_Type is private;
   with function " = " (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Vectors is
   pragma Preelaborate(Vectors);
   pragma Remote_Types(Vectors);

   subtype Extended_Index is
      Index_Type'Base range
         Index_Type'First-1 ..
         Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1;
   No_Index : constant Extended_Index := Extended_Index'First;

   type Vector is tagged private
      with Constant_Indexing => Constant_Reference,
           Variable_Indexing => Reference,
           Default_Iterator  => Iterate,
           Iterator_Element  => Element_Type;
   pragma Preelaborable_Initialization(Vector);

   type Cursor is private;
   pragma Preelaborable_Initialization(Cursor);

   Empty_Vector : constant Vector;

   No_Element : constant Cursor;

   function Has_Element (Position : Cursor) return Boolean;

   package Vector_Iterator_Interfaces is new
       Ada.Iterator_Interfaces (Cursor, Has_Element);

   function " = " (Left, Right : Vector) return Boolean;

   function To_Vector (Length : Count_Type) return Vector;

   function To_Vector
     (New_Item : Element_Type;
      Length   : Count_Type) return Vector;

   function "&" (Left, Right : Vector) return Vector;

   function "&" (Left  : Vector;
                 Right : Element_Type) return Vector;

   function "&" (Left  : Element_Type;
                 Right : Vector) return Vector;

   function "&" (Left, Right  : Element_Type) return Vector;

   function Capacity (Container : Vector) return Count_Type;

   procedure Reserve_Capacity (Container : in out Vector;
                               Capacity  : in     Count_Type);

   function Length (Container : Vector) return Count_Type;

   procedure Set_Length (Container : in out Vector;
                         Length    : in     Count_Type);

   function Is_Empty (Container : Vector) return Boolean;

   procedure Clear (Container : in out Vector);

   function To_Cursor (Container : Vector;
                       Index     : Extended_Index) return Cursor;

   function To_Index (Position  : Cursor) return Extended_Index;

   function Element (Container : Vector;
                     Index     : Index_Type)
      return Element_Type;

   function Element (Position : Cursor) return Element_Type;

   procedure Replace_Element (Container : in out Vector;
                              Index     : in     Index_Type;
                              New_Item  : in     Element_Type);

   procedure Replace_Element (Container : in out Vector;
                              Position  : in     Cursor;
                              New_item  : in     Element_Type);

   procedure Query_Element
     (Container : in Vector;
      Index     : in Index_Type;
      Process   : not null access procedure (Element : in Element_Type));

   procedure Query_Element
     (Position : in Cursor;
      Process  : not null access procedure (Element : in Element_Type));

   procedure Update_Element
     (Container : in out Vector;
      Index     : in     Index_Type;
      Process   : not null access procedure
                      (Element : in out Element_Type));

   procedure Update_Element
     (Container : in out Vector;
      Position  : in     Cursor;
      Process   : not null access procedure
                      (Element : in out Element_Type));

   type Constant_Reference_Type
         (Element : not null access constant Element_Type) is private
      with Implicit_Dereference => Element;

   type Reference_Type (Element : not null access Element_Type) is private
      with Implicit_Dereference => Element;

   function Constant_Reference (Container : aliased in Vector;
                                Index     : in Index_Type)
      return Constant_Reference_Type;

   function Reference (Container : aliased in out Vector;
                       Index     : in Index_Type)
      return Reference_Type;

   function Constant_Reference (Container : aliased in Vector;
                                Position  : in Cursor)
      return Constant_Reference_Type;

   function Reference (Container : aliased in out Vector;
                       Position  : in Cursor)
      return Reference_Type;

   procedure Assign (Target : in out Vector; Source : in Vector);

   function Copy (Source : Vector; Capacity : Count_Type := 0)
      return Vector;

   procedure Move (Target : in out Vector;
                   Source : in out Vector);

   procedure Insert (Container : in out Vector;
                     Before    : in     Extended_Index;
                     New_Item  : in     Vector);

   procedure Insert (Container : in out Vector;
                     Before    : in     Cursor;
                     New_Item  : in     Vector);

   procedure Insert (Container : in out Vector;
                     Before    : in     Cursor;
                     New_Item  : in     Vector;
                     Position  :    out Cursor);

   procedure Insert (Container : in out Vector;
                     Before    : in     Extended_Index;
                     New_Item  : in     Element_Type;
                     Count     : in     Count_Type := 1);

   procedure Insert (Container : in out Vector;
                     Before    : in     Cursor;
                     New_Item  : in     Element_Type;
                     Count     : in     Count_Type := 1);

   procedure Insert (Container : in out Vector;
                     Before    : in     Cursor;
                     New_Item  : in     Element_Type;
                     Position  :    out Cursor;
                     Count     : in     Count_Type := 1);

   procedure Insert (Container : in out Vector;
                     Before    : in     Extended_Index;
                     Count     : in     Count_Type := 1);

   procedure Insert (Container : in out Vector;
                     Before    : in     Cursor;
                     Position  :    out Cursor;
                     Count     : in     Count_Type := 1);

   procedure Prepend (Container : in out Vector;
                      New_Item  : in     Vector);

   procedure Prepend (Container : in out Vector;
                      New_Item  : in     Element_Type;
                      Count     : in     Count_Type := 1);

   procedure Append (Container : in out Vector;
                     New_Item  : in     Vector);

   procedure Append (Container : in out Vector;
                     New_Item  : in     Element_Type;
                     Count     : in     Count_Type := 1);

   procedure Insert_Space (Container : in out Vector;
                           Before    : in     Extended_Index;
                           Count     : in     Count_Type := 1);

   procedure Insert_Space (Container : in out Vector;
                           Before    : in     Cursor;
                           Position  :    out Cursor;
                           Count     : in     Count_Type := 1);

   procedure Delete (Container : in out Vector;
                     Index     : in     Extended_Index;
                     Count     : in     Count_Type := 1);

   procedure Delete (Container : in out Vector;
                     Position  : in out Cursor;
                     Count     : in     Count_Type := 1);

   procedure Delete_First (Container : in out Vector;
                           Count     : in     Count_Type := 1);

   procedure Delete_Last (Container : in out Vector;
                          Count     : in     Count_Type := 1);

   procedure Reverse_Elements (Container : in out Vector);

   procedure Swap (Container : in out Vector;
                   I, J      : in     Index_Type);

   procedure Swap (Container : in out Vector;
                   I, J      : in     Cursor);

   function First_Index (Container : Vector) return Index_Type;

   function First (Container : Vector) return Cursor;

   function First_Element (Container : Vector)
      return Element_Type;

   function Last_Index (Container : Vector) return Extended_Index;

   function Last (Container : Vector) return Cursor;

   function Last_Element (Container : Vector)
      return Element_Type;

   function Next (Position : Cursor) return Cursor;

   procedure Next (Position : in out Cursor);

   function Previous (Position : Cursor) return Cursor;

   procedure Previous (Position : in out Cursor);

   function Find_Index (Container : Vector;
                        Item      : Element_Type;
                        Index     : Index_Type := Index_Type'First)
      return Extended_Index;

   function Find (Container : Vector;
                  Item      : Element_Type;
                  Position  : Cursor := No_Element)
      return Cursor;

   function Reverse_Find_Index (Container : Vector;
                                Item      : Element_Type;
                                Index     : Index_Type := Index_Type'Last)
      return Extended_Index;

   function Reverse_Find (Container : Vector;
                          Item      : Element_Type;
                          Position  : Cursor := No_Element)
      return Cursor;

   function Contains (Container : Vector;
                      Item      : Element_Type) return Boolean;


   procedure  Iterate
     (Container : in Vector;
      Process   : not null access procedure (Position : in Cursor));

   procedure Reverse_Iterate
     (Container : in Vector;
      Process   : not null access procedure (Position : in Cursor));

   function Iterate (Container : in Vector)
      return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

   function Iterate (Container : in Vector; Start : in Cursor)
      return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

   generic
      with function "<" (Left, Right : Element_Type)
         return Boolean is <>;
   package Generic_Sorting is

      function Is_Sorted (Container : Vector) return Boolean;

      procedure Sort (Container : in out Vector);

      procedure Merge (Target  : in out Vector;
                       Source  : in out Vector);

   end Generic_Sorting;

private

   ... -- not specified by the language

end Ada.Containers.Vectors;

Спасибо за ответ. Я знал о векторах, но пытался сделать это только с помощью ограниченных массивов. Например, моя процедура принимает ограниченный массив и возвращает другой ограниченный массив. Но я думаю, что это невозможно. Я имею в виду, что сама суть Ады заключается в использовании ограниченных вещей.

Daniel Constantinescu 28.05.2019 07:49
Ada.Containers.Bounded_Vectors, АРМ А.18.19
Simon Wright 28.05.2019 09:22

Другие вопросы по теме