Ada 编程/字符串
Ada 支持三种不同的字符串类型。每种字符串类型旨在解决不同的问题。
此外,每种字符串类型都针对每种可用的字符类型 (Character, Wide_Character, Wide_Wide_Character) 实现,共计九种组合。
固定长度字符串(预定义类型 String)是 字符数组,因此长度固定。由于 String 是一个 不确定的子类型,因此长度不需要在编译时知道 - 长度可以在运行时计算出来。在以下示例中,长度是从命令行参数 1 计算出来的
X : String := Ada.Command_Line.Argument (1);
但是,一旦长度被计算出来并且字符串被创建,长度将保持不变。尝试以下程序,它展示了一个典型的错误
with
Ada.Text_IO;with
Ada.Command_Line;procedure
Show_Commandline_1is
package
T_IOrenames
Ada.Text_IO;package
CLrenames
Ada.Command_Line; X : String := CL.Argument (1);begin
T_IO.Put ("Argument 1 = "); T_IO.Put_Line (X); X := CL.Argument (2); T_IO.Put ("Argument 2 = "); T_IO.Put_Line (X);end
Show_Commandline_1;
该程序仅当第 1 个和第 2 个参数具有相同的长度时才有效。即使第 2 个参数更短,情况也是如此。没有对较短字符串的自动填充,也没有对较长字符串的自动截断。
话虽如此,包 Ada.Strings.Fixed 包含一组用于固定长度字符串处理的程序和函数,允许填充较短字符串和截断较长字符串。
尝试以下示例以查看其工作原理
with
Ada.Text_IO;with
Ada.Command_Line;with
Ada.Strings.Fixed;procedure
Show_Commandline_2is
package
T_IOrenames
Ada.Text_IO;package
CLrenames
Ada.Command_Line;package
Srenames
Ada.Strings;package
SFrenames
Ada.Strings.Fixed; X : String := CL.Argument (1);begin
T_IO.Put ("Argument 1 = "); T_IO.Put_Line (X); SF.Move ( Source => CL.Argument (2), Target => X, Drop => S.Right, Justify => S.Left, Pad => S.Space); T_IO.Put ("Argument 2 = "); T_IO.Put_Line (X);end
Show_Commandline_2;
当已知和/或限制字符串的最大长度时,可以使用有界长度字符串。这在数据库应用程序中很常见,在数据库应用程序中,只能存储有限数量的字符。
与固定长度字符串一样,最大长度不需要在编译时知道 - 它也可以在运行时计算出来 - 如下面的示例所示
with
Ada.Text_IO;with
Ada.Command_Line;with
Ada.Strings.Bounded;procedure
Show_Commandline_3is
package
T_IOrenames
Ada.Text_IO;package
CLrenames
Ada.Command_Line;function
Max_Length ( Value_1 : Integer; Value_2 : Integer)return
Integeris
Retval : Integer;begin
if
Value_1 > Value_2then
Retval := Value_1;else
Retval := Value_2;end
if
;return
Retval;end
Max_Length;pragma
Inline (Max_Length);package
SBis
new
Ada.Strings.Bounded.Generic_Bounded_Length ( Max => Max_Length ( Value_1 => CL.Argument (1)'Length, Value_2 => CL.Argument (2)'Length)); X : SB.Bounded_String := SB.To_Bounded_String (CL.Argument (1));begin
T_IO.Put ("Argument 1 = "); T_IO.Put_Line (SB.To_String (X)); X := SB.To_Bounded_String (CL.Argument (2)); T_IO.Put ("Argument 2 = "); T_IO.Put_Line (SB.To_String (X));end
Show_Commandline_3;
您应该知道,有界长度字符串有一些明显的缺点。最明显的是,每个有界长度字符串都是一个不同的类型,这使得转换它们相当麻烦。此外,有界长度字符串类型始终为类型允许的最大字符串长度分配内存。有界长度字符串的内存分配等于最大字符串“字符”数加上一个实现相关的数字,其中包含字符串长度(每个字符可能需要分配超过一个字节的字符,具体取决于字符串的底层字符类型,而长度数字对于 Windows GNAT Ada 编译器 v3.15p 来说是 4 个字节,例如)。
最后但并非最不重要的是无界长度字符串。事实上:如果您没有进行嵌入式或数据库编程,这将是您最常使用的字符串类型,因为它为您提供了最大的灵活性。
顾名思义,无界长度字符串可以保存几乎任何长度的字符串 - 仅限于 Integer'Last 的值或您的可用堆内存。这是因为 Unbounded_String 类型在幕后使用动态内存分配,提供较低的效率但最大的灵活性。
with
Ada.Text_IO;with
Ada.Command_Line;with
Ada.Strings.Unbounded;procedure
Show_Commandline_4is
package
T_IOrenames
Ada.Text_IO;package
CLrenames
Ada.Command_Line;package
SUrenames
Ada.Strings.Unbounded; X : SU.Unbounded_String := SU.To_Unbounded_String (CL.Argument (1));begin
T_IO.Put ("Argument 1 = "); T_IO.Put_Line (SU.To_String (X)); X := SU.To_Unbounded_String (CL.Argument (2)); T_IO.Put ("Argument 2 = "); T_IO.Put_Line (SU.To_String (X));end
Show_Commandline_4;
如您所见,无界长度字符串示例也是最短的 (不考虑有错误的第一个示例) - 这使得使用无界长度字符串非常吸引人。