麻烦通用链表

时间:2016-03-09 18:48:11

标签: generics ada gnat

我正在学习Ada中的泛型,所以我实现了一个简单的链表。这是我的代码:

dictionary

Linked_List.ads:

Linked_List.adb :
    package body Linked_List is
   function Get_First_Element return Element_Type is
   begin
       return Beginning.Value;
   end Get_First_Element;

   function Get_Last_Element return Element_Type is
      temp : Node := Beginning.all;
   begin
      while temp.Next /= null loop
         temp := temp.Next.all;
      end loop;
      return temp.Value;
   end Get_Last_Element;

   procedure Add_Element(data : Element_Type) is
      newNode : access Node;
   begin
      newNode := new Node;
      newNode.all.Value := data;
      if Beginning.all.Next = null then
         Beginning := newNode;
      else
         Last.Next := newNode;
         Last := newNode;
      end if;

   end Add_Element; 

   procedure Remove_Element(data : Element_Type) is 
      temp : access Node := Beginning;
      prev : Node;
   begin
      while temp /= null or temp.all.Value /= data loop
         prev := temp.all;
         temp := temp.Next;
      end loop;
      if temp = null then
         return;
      else
         prev.Next := temp.all.Next;
      end if;
   end Remove_Element;

   function Exists(data : Element_Type) return Boolean is
      temp : access Node := Beginning;
   begin
      while temp /= null or temp.all.Value /= data loop
         temp := temp.Next;
      end loop;
      if temp = null then
         return false;
      end if;
      return true;
   end Exists;
begin
   Beginning.all.Next := Last;
end Linked_List;

两个文件是否编译正常。这是我的主要程序:

generic
   type Element_Type is private;
package Linked_List is 
   function Get_First_Element return Element_Type;
   function Get_Last_Element return Element_Type;
   procedure Add_Element(data : Element_Type);
   procedure Remove_Element(data : Element_Type);
   function Exists(data : Element_Type) return Boolean;
private
   type Node is 
      record
            Value : Element_Type;
            Next : access Node;
      end record;
   Beginning : access Node;
   Last : access Node;
end Linked_List;

这是我遇到问题的地方。以下是编译器给出的错误:

With Ada.Text_IO; use Ada.Text_IO;
with Linked_List;
procedure Main is
   package List is new Linked_List(Element_Type => Integer);
   lst : List;
begin

   for i in -5..5 loop
      lst.Add_Element(i);
   end loop;
   lst.Remove_Element(1);
   Put_Line(lst.Exists(2));
end Main;

我无法理解这个错误:

main.adb:5:10: subtype mark required in this context
main.adb:5:10: found "List" declared at line 4
main.adb:5:14: incorrect constraint for this kind of type
main.adb:9:07: invalid prefix in selected component "lst"
main.adb:11:04: invalid prefix in selected component "lst"
main.adb:12:13: invalid prefix in selected component "lst"

我可以理解其他错误告诉我的内容。

编辑:我修复了部分代码,我收到了新的错误消息,所有内容都已更新。

1 个答案:

答案 0 :(得分:1)

包本质上是名称空间,而不是类。因此,您无法创建该包的对象(实例),该对象不会导出任何类型。

所以你声明的东西就像一个单身人士:在你的情况下,只能有一个(每个通用实例化),名为List。 并列出您可以使用的导出子程序。

因此,删除声明lst : List;并直接调用子程序List.Add_Element(i);,您的示例应该可行。

如果您需要更多链接列表,可以根据需要多次实例化泛型。您在每次调用中使用的列表由实例化的包名称确定。

如果要创建包中声明的类型的对象,则必须在包中声明类型;在公共部分添加行type Node is private;就是您需要做的;虽然type Node_Acc is access node;通常也很有用,但请将Beginning,Last的声明更新为此类型。

然后每个子程序需要知道它们在哪个节点上运行;所以他们需要一个Node作为参数,例如function Get_First_Element(this : Node) return Element_Type;

现在您可以声明Node类型的对象并将它们作为参数传递。 如果记录是带标记的记录,您可以使用function(argument)object.method表示法,无论哪种方式都可以使程序更容易理解。

-- package
type Node is tagged private;
private
type Node is tagged record ...;

-- client code
    Head : List.Node;
    ...
    Add_Element(Head,1);
    Head.Add_Element(2);