当 Vector 包含字符串时,"Element_Type" 的 Ada 错误实际值必须是明确的子类型
Ada Error actual for "Element_Type" must be a definite subtype when Vector contains Strings
我的目标是在括号中打印所有形式的具有 N 个节点的树,可以根据 Context-Free 语法定义如下:
T → 树是空的
T → (T.T) 左右为 children
的节点
例如,所有具有 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" 错误。
确定子类型是其大小在编译时已知的子类型。有关它的更多信息,您可以在 Ada Wikibooks 中找到。您的字符串没有声明长度,因此是不确定类型。
解决方案:
- 如果你知道要存储在Vector中的String的大小,你可以声明它,例如:
package String_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => String(1 .. 20));
- 改用Unbounded_String,这也需要更改您的进一步代码(要在任何地方使用Unbounded_String或将其转换为字符串):
package String_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => Unbounded_String);
- 使用Indefinite_Vector代替Vector:
package String_Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Natural,
Element_Type => String);
所有下一个错误(这个也带有“&”)是第一个问题的结果,错误定义了 String_Vectors)。
更新到新版问题:
这里还有几点需要注意:
- 追加(第 21 和 22 行)- 当您想将一种类型添加到另一种类型时(在您的示例中,字符串和向量游标),您必须将其中一个转换为另一个。因此,这一行应该看起来是:
Strings.Append("(" & Natural'Image(String_Vectors.To_Index(T)) & ".)");
首先将向量 Cursor 转换为 Natural,然后将其转换为 String,以便连接它们。
- Put_Line(第 29 行)- 在 Ada 中,您不能以这种方式打印 Vectors(如果我猜对了,这就是您想要做的?)如果您想打印 vector 的内容,您必须打印它的每个元素:
for Item of Tree(X) loop
Put_Line(Item);
end loop;
其他错误应该又出现了,这两个问题的影响(至少所有的东西都为我编译并且工作)。
我的目标是在括号中打印所有形式的具有 N 个节点的树,可以根据 Context-Free 语法定义如下:
T → 树是空的
T → (T.T) 左右为 children
的节点例如,所有具有 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" 错误。
确定子类型是其大小在编译时已知的子类型。有关它的更多信息,您可以在 Ada Wikibooks 中找到。您的字符串没有声明长度,因此是不确定类型。
解决方案:
- 如果你知道要存储在Vector中的String的大小,你可以声明它,例如:
package String_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => String(1 .. 20));
- 改用Unbounded_String,这也需要更改您的进一步代码(要在任何地方使用Unbounded_String或将其转换为字符串):
package String_Vectors is new Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => Unbounded_String);
- 使用Indefinite_Vector代替Vector:
package String_Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Natural,
Element_Type => String);
所有下一个错误(这个也带有“&”)是第一个问题的结果,错误定义了 String_Vectors)。
更新到新版问题:
这里还有几点需要注意:
- 追加(第 21 和 22 行)- 当您想将一种类型添加到另一种类型时(在您的示例中,字符串和向量游标),您必须将其中一个转换为另一个。因此,这一行应该看起来是:
Strings.Append("(" & Natural'Image(String_Vectors.To_Index(T)) & ".)");
首先将向量 Cursor 转换为 Natural,然后将其转换为 String,以便连接它们。
- Put_Line(第 29 行)- 在 Ada 中,您不能以这种方式打印 Vectors(如果我猜对了,这就是您想要做的?)如果您想打印 vector 的内容,您必须打印它的每个元素:
for Item of Tree(X) loop
Put_Line(Item);
end loop;
其他错误应该又出现了,这两个问题的影响(至少所有的东西都为我编译并且工作)。