当Vector包含字符串时,“ Element_Type”的Ada实际错误必须是一个确定的子类型

时间:2019-09-05 17:29:48

标签: ada

我的目标是用括号表示法打印带有N个节点的所有形式的树,可以根据上下文无关的语法定义如下:

T→树为空

T→(T.T)一个带有左右子节点的节点

例如,所有具有3个节点的树将如下所示:

((((。)。)。)

((。(。))。)

((...(。))

(。(((。)。))

(。(。(。)))

我已经用Ada编写了以下代码,

with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;

with Ada.Text_IO; use Ada.Text_IO;

with Ada.Command_Line;
procedure Ass1 is 
     X: Positive := Positive'Value(Ada.Command_Line.Argument(1));
    package String_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Natural,
      Element_Type => String);

    function tree(N: Integer) return String_Vectors.Vector is
    Strings : String_Vectors.Vector;    
    begin
        if N = 1 then
            Strings.Append("(.)");
            return Strings;
        end if;
        for T in tree(N - 1).Iterate loop
            Strings.Append("(" & T & ".)");
            Strings.Append("(." & T & ")");
        end loop;
    return Strings;
    end tree;


begin
    Ada.Text_IO.Put_Line(Ass1(X));
end;

但是我得到这个错误:

ass1.adb:9:09: instantiation error at a-convec.ads:375
ass1.adb:9:09: unconstrained element type in array declaration
ass1.adb:11:27: actual for "Element_Type" must be a definite subtype
ass1.adb:21:36: invalid operand types for operator "&"
ass1.adb:22:37: invalid operand types for operator "&"
ass1.adb:29:16: no candidate interpretations match the actuals:
ass1.adb:29:16: missing argument for parameter "Item" in call to "Put_Line" declared at a-textio.ads:259
ass1.adb:29:26: expected type "Standard.String"
ass1.adb:29:26: found private type "Ada.Containers.Vectors.Vector" from instance at line 9
ass1.adb:29:26:   ==> in call to "Put_Line" at a-textio.ads:263
x86_64-linux-gnu-gnatmake-7: "ass1.adb" compilation error

什么是定型子类型,为什么String不是一个子类型?我以为&在Ada中用于字符串连接。

---------编辑---------- 我根据答案将代码更改为以下代码:

with Ada.Containers; use Ada.Containers;
with Ada.Containers.Indefinite_Vectors;

with Ada.Text_IO; use Ada.Text_IO;

with Ada.Command_Line;
procedure Tree is
         X: Positive := Positive'Value(Ada.Command_Line.Argument(1));
        package String_Vectors is new Ada.Containers.Indefinite_Vectors
         (Index_Type   => Natural,
          Element_Type => String);

        function Tree(N: Integer) return String_Vectors.Vector is
        Strings : String_Vectors.Vector;
        begin
            if N = 1 then
                Strings.Append("(.)");
                return Strings;
            end if;
            for T in Tree(N - 1).Iterate loop
                Strings.Append("(" & T & ".)");
                Strings.Append("(." & T & ")");
            end loop;
        return Strings;
        end Tree;


begin
    Ada.Text_IO.Put_Line(Tree(X));
end;

但是我仍然收到以下错误:

gnatmake tree.adb 6
gcc -c tree.adb
tree.adb:21:36: invalid operand types for operator "&"
tree.adb:22:37: invalid operand types for operator "&"
tree.adb:29:16: no candidate interpretations match the actuals:
tree.adb:29:16: missing argument for parameter "Item" in call to "Put_Line" declared at a-textio.ads\
:498
tree.adb:29:26: expected type "Standard.String"
tree.adb:29:26: found private type "Ada.Containers.Indefinite_Vectors.Vector" from instance at line \
9
tree.adb:29:26:   ==> in call to "Put_Line" at a-textio.ads:508
gnatmake: "tree.adb" compilation error

操作数问题仍然存在。根据文档,Put_Line可以接受一个参数,那么为什么缺少参数?而且我也不理解私有类型“ Indefinite_Vectors.Vector”错误。

1 个答案:

答案 0 :(得分:5)

确定子类型是其大小在编译时已知的子类型。有关详细信息,请参见Ada Wikibooks。您的字符串没有声明的长度,因此是不确定的类型。

解决方案:

  1. 如果您知道将存储在Vector中的String的大小,则可以对其进行声明,例如:
    package String_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Natural,
      Element_Type => String(1 .. 20));
  1. 改为使用Unbounded_String,这也将需要更改您的其他代码(在各处使用Unbounded_String或将其强制转换为String):
    package String_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Natural,
      Element_Type => Unbounded_String);
  1. 使用Indefinite_Vector代替Vector:
    package String_Vectors is new Ada.Containers.Indefinite_Vectors
     (Index_Type   => Natural,
      Element_Type => String);

所有下一个错误(第一个也带有“&”的错误)是第一个问题,其错误定义了String_Vectors。


已更新为新版本的问题:

这里还有几件事需要注意:

  1. 追加(第21和22行)-当您想将一种类型添加到另一种类型(在您的示例中是字符串和向量光标)时,必须将其中一种强制转换为另一种。因此,此行应如下所示:
Strings.Append("(" & Natural'Image(String_Vectors.To_Index(T)) & ".)");

首先将向量Cursor转换为Natural,然后将其转换为String,以便可以将它们连接起来。

  1. Put_Line(第29行)-在Ada中,您不能以这种方式打印Vector(如果我很好想,这就是您要执行的操作?)如果要打印Vector的内容,则必须打印每个其元素:
for Item of Tree(X) loop
   Put_Line(Item);
end loop;

其他错误应该再次出现,这是这两个问题的影响(至少所有内容对于我来说都是可以编译的并且可以正常工作)。