为什么字符串需要初始化一个初始值?
Why do strings need to be initialized with an initial value?
我有一个字符串 lx : String
,我想稍后在我的代码中设置该值,但我收到错误 unconstrained subtype not allowed (need initialization) provide initial value or explicit array bounds
我还有一个字符串数组L_array : array (1 .. user_size) of String;
,它抛出错误unconstrained element type in array declaration
。我无法从一开始就对其进行初始化,因为这些值是从文本文件中读入的。如果我想稍后设置这些值,我该怎么办?
Ada 的字符串类型定义为
type String is array(Positive range <>) of Character
。这需要一个初始范围来声明一个变量,通过given an initial string or given a range constraint,否则编译器将无法知道对象有多大。
查看 Rosettacode 中的示例,了解如何从文件中读取。
这里确实有两个问题,但具有相同的根本原因:String
在创建时必须固定其大小(即约束)。
如果您知道它的大小,并且(在 array of String
的情况下)所有 String
的大小都相同,那么限制它们很容易,不需要进一步的评论。
想想 String
未知长度意味着什么:未知的存储要求。一种方法是使用指针或访问类型,分配存储空间来保存字符串,并记得稍后释放它。与其他语言一样,这种方式可能会出现错误、内存泄漏等。猜测大小上限的替代方法也是如此,这会带来缓冲区溢出的可能性。您可以像在其他语言中一样在 Ada 中执行此操作,但是...不是最佳实践。
Ada 分别以 Unbounded_String
和 Bounded_String
的形式提供了对这两种模式的抽象,旨在最大限度地减少问题。但是使用起来还是不如String
.
有一个 somewhat intense discussion of these abstractions on the comp.lang.ada 新闻组(我很抱歉使用 Google Groups 网关)
因此,我将建议您使用 String
.
完成这两项任务的方法
对于稍后设置值的单个字符串 lx : String
的情况,答案很简单:只需稍后声明 String
,用该值初始化。而不是
lx : String;
...
lx := Read(My_File);
Process_String(lx);
使用声明块(通常在循环体中):
...
declare
lx : String := Read(My_File);
begin
Process_String(lx);
end;
在 end
处,字符串 lx
超出范围,并重新创建(具有正确的大小,从初始化开始,下次到达 declare
块时。
如果每个成员的大小不同,Array of String
会更难,Bounded_String
或 Unbounded_String
是有用的候选者。
但是另一种方法(自 Ada-2005 起)是使用 Ada.Containers
包而不是数组。它们有 Definite 和 Indefinite 两种类型,您需要一个 Indefinite 容器来存储不同大小的成员。具体来说 Ada.Containers.Indefinite_Vectors
作为 Vector 可以像 Array 一样进行索引。
这种方式与在C++中使用std_vector
有相似之处,实际上标准模板库最初是为Ada设计的,后来适应了C++。
在 Ada-2005 之前,Ada.Containers
不是该语言的一部分,但您可以使用来自外部库的等效项,例如(我认为)Booch 组件 (Grady Booch)。
首发:
with Ada.Containers.Indefinite_Vectors;
with Ada.Text_IO;
procedure String_Vector is
User_Size : constant natural := 10;
subtype Index is natural range 1 .. User_Size;
-- Indefinite_Vectors is a generic package.
-- You can't use it directly, instantiate it with index and content types
package String_Holder is new Ada.Containers.Indefinite_Vectors(Index,String);
-- make String_Holder operations visible
use String_Holder;
LV : String_Holder.Vector; -- initially empty
L_Vector : String_Holder.Vector := -- initialise to size with empty elements
To_Vector(Ada.Containers.Count_Type(User_Size));
begin
L_Vector.Replace_Element(1,"hello");
LV.Append("world");
Ada.Text_IO.Put_Line(L_Vector(1) & " " & LV(1));
end String_Vector;
我有一个字符串 lx : String
,我想稍后在我的代码中设置该值,但我收到错误 unconstrained subtype not allowed (need initialization) provide initial value or explicit array bounds
我还有一个字符串数组L_array : array (1 .. user_size) of String;
,它抛出错误unconstrained element type in array declaration
。我无法从一开始就对其进行初始化,因为这些值是从文本文件中读入的。如果我想稍后设置这些值,我该怎么办?
Ada 的字符串类型定义为
type String is array(Positive range <>) of Character
。这需要一个初始范围来声明一个变量,通过given an initial string or given a range constraint,否则编译器将无法知道对象有多大。
查看 Rosettacode 中的示例,了解如何从文件中读取。
这里确实有两个问题,但具有相同的根本原因:String
在创建时必须固定其大小(即约束)。
如果您知道它的大小,并且(在 array of String
的情况下)所有 String
的大小都相同,那么限制它们很容易,不需要进一步的评论。
想想 String
未知长度意味着什么:未知的存储要求。一种方法是使用指针或访问类型,分配存储空间来保存字符串,并记得稍后释放它。与其他语言一样,这种方式可能会出现错误、内存泄漏等。猜测大小上限的替代方法也是如此,这会带来缓冲区溢出的可能性。您可以像在其他语言中一样在 Ada 中执行此操作,但是...不是最佳实践。
Ada 分别以 Unbounded_String
和 Bounded_String
的形式提供了对这两种模式的抽象,旨在最大限度地减少问题。但是使用起来还是不如String
.
有一个 somewhat intense discussion of these abstractions on the comp.lang.ada 新闻组(我很抱歉使用 Google Groups 网关)
因此,我将建议您使用 String
.
对于稍后设置值的单个字符串 lx : String
的情况,答案很简单:只需稍后声明 String
,用该值初始化。而不是
lx : String;
...
lx := Read(My_File);
Process_String(lx);
使用声明块(通常在循环体中):
...
declare
lx : String := Read(My_File);
begin
Process_String(lx);
end;
在 end
处,字符串 lx
超出范围,并重新创建(具有正确的大小,从初始化开始,下次到达 declare
块时。
如果每个成员的大小不同,Array of String
会更难,Bounded_String
或 Unbounded_String
是有用的候选者。
但是另一种方法(自 Ada-2005 起)是使用 Ada.Containers
包而不是数组。它们有 Definite 和 Indefinite 两种类型,您需要一个 Indefinite 容器来存储不同大小的成员。具体来说 Ada.Containers.Indefinite_Vectors
作为 Vector 可以像 Array 一样进行索引。
这种方式与在C++中使用std_vector
有相似之处,实际上标准模板库最初是为Ada设计的,后来适应了C++。
在 Ada-2005 之前,Ada.Containers
不是该语言的一部分,但您可以使用来自外部库的等效项,例如(我认为)Booch 组件 (Grady Booch)。
首发:
with Ada.Containers.Indefinite_Vectors;
with Ada.Text_IO;
procedure String_Vector is
User_Size : constant natural := 10;
subtype Index is natural range 1 .. User_Size;
-- Indefinite_Vectors is a generic package.
-- You can't use it directly, instantiate it with index and content types
package String_Holder is new Ada.Containers.Indefinite_Vectors(Index,String);
-- make String_Holder operations visible
use String_Holder;
LV : String_Holder.Vector; -- initially empty
L_Vector : String_Holder.Vector := -- initialise to size with empty elements
To_Vector(Ada.Containers.Count_Type(User_Size));
begin
L_Vector.Replace_Element(1,"hello");
LV.Append("world");
Ada.Text_IO.Put_Line(L_Vector(1) & " " & LV(1));
end String_Vector;