如何在 Ada 中定义字符串数组?

How can I define an Array of Strings in Ada?

提问人:Macia Salva 提问时间:2/3/2022 最后编辑:trashgodMacia Salva 更新时间:7/24/2022 访问量:542

问:

我想要的是在 Ada 中定义一个字符串数组。

我正在尝试执行以下代码:

type String is array (Positive range <>) of Character;
type lexicon is array(1..7) of String(1..20);
nomFumadors : lexicon := ("Macia","Xisco","Toni","Laura","Rocky","Paz");
nomNoFumadors : lexicon := ("Marina","Marta","Joan","Africa","America");

编译器说:

warning:wrong length for array of subtype of "String" defined at line 42

我的第 42 行是这样的:

type lexicon is array(1..7) of String(1..20);

但公司表示,警告在第 43 行和第 44 行:这些是什么:

nomFumadors : lexicon := ("Macia","Xisco","Toni","Laura","Rocky","Paz");
nomNoFumadors : lexicon := ("Marina","Marta","Joan","Africa","America");

有人可以帮我吗?

数组 字符串 警告 ADA

评论

0赞 Jeffrey R. Carter 2/4/2022
标准免责声明:这里讨论的语言是以女性命名的,因此应大写为 Ada。

答:

5赞 flyx 2/3/2022 #1

您声明了数组以保存长度为 20 的字符串。您提供的字符串文本长度少于 20 个字符。因此出现错误。

您似乎正在寻找最多包含 20 个字符的字符串类型。这在以下语言中提供:Ada.Strings.Bounded

package Max_20_String is new Ada.Strings.Bounded.Generic_Bounded_Length (20);
use Max_20_String;

type Lexicon is array (1..7) of Bounded_String; -- from Max_20_String
nomFumadors : Lexicon := (To_Bounded_String ("Macia"),
                          To_Bounded_String ("Xisco"),
                          To_Bounded_String ("Toni"),
                          To_Bounded_String ("Laura"),
                          To_Bounded_String ("Rocky"),
                          To_Bounded_String ("Paz"));

要从Bounded_String中取回字符串,请使用 例如.To_String (Lexicon (2))

5赞 Zerte 2/3/2022 #2

另一种选择是(顾名思义,长度是可变的和无限的):Unbounded_String

with Ada.Strings.Unbounded;

procedure Fumador is
  use Ada.Strings.Unbounded;

  subtype VString is Unbounded_String;
  function "+" (Source : in String) return VString renames To_Unbounded_String;

  type Lexicon is array (Integer range <>) of VString;  --  Unknown number of people.
  nomFumadors : Lexicon := (+"Macia", +"Xisco", +"Toni", +"Laura", +"Rocky", +"Paz");
  nomNoFumadors : Lexicon := (+"Marina", +"Marta", +"Joan", +"Africa", +"America");
  
begin
  null;
end;

评论

1赞 2/3/2022
当然,函数重命名将在两个答案中都有效。
6赞 Jere 2/4/2022 #3

其他人则提到了有界和无界字符串。您也可以使用Indefinite_Vectors。您可以使用“&”运算符来初始化它们(与初始值设定项列表相反,尽管 Ada 的下一个版本正在将初始值设定项列表添加到容器中)。你可以像数组一样使用向量,通过传入索引,此外,你还能获得许多其他附加功能。

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

procedure Hello is

    package Vectors is new Ada.Containers.Indefinite_Vectors
        (Index_Type   => Positive,
         Element_Type => String);
         
    use type Vectors.Vector;
         
    nomFumadors   : Vectors.Vector 
        := Vectors.Empty_Vector 
            & "Macia" 
            & "Xisco" 
            & "Toni" 
            & "Laura" 
            & "Rocky" 
            & "Paz";
    nomNoFumadors : Vectors.Vector
        := Vectors.Empty_Vector 
            & "Marina" 
            & "Marta" 
            & "Joan" 
            & "Africa" 
            & "America";
begin
    Put_Line("Hello, world!");
    
    -- Loop through Elements
    for Name of nomFumadors loop
        Put_Line(Name);
    end loop;
    
    -- Loop by index
    for Index in nomNoFumadors.Iterate loop
        Put_Line(nomNoFumadors(Index));
    end loop;
    
end Hello;
1赞 Jeffrey R. Carter 2/4/2022 #4

另一种解决方案是使用 String,截断长字符串并填充短字符串:

Max : constant := 20;
subtype S20 is String (1 .. Max);
type Lexicon is array (1 .. 7) of S20;
function To20 (S : in String) return S20 is
   (if S'Length >= Max then S (S'First .. S'First + Max - 1)
    else S & (S'Length + 1 .. Max => ' ') );
V : Lexicon := (To20 (""), To20 ("Hello"), To20 ("1234567890123456789012345"), ...
0赞 Mark 2/9/2022 #5

类似于 Jeff Carter 的回答,但使用函数将任何字符串强制转换为固定字符串......

procedure Main is
   
   subtype Lexicon_Data is String (1 .. 20);
   type Lexicon is array (1 .. 7) of Lexicon_Data;
   
   function To_Lexicon_Data
     (Value : in String)
      return Lexicon_Data
   is
      Result : Lexicon_Data;
   begin
      
      if Value'Length < 1 then
         -- Empty string returns a bunch of spaces
         Result := (others => ' ');
         
      else
         declare
            Offset : constant Natural :=
              Value'First - Lexicon_Data'First;
         begin
            
            if Value'Length > Lexicon_Data'Length then
               -- Length exceeds range, so truncate
               Result (Lexicon_Data'Range) := Lexicon_Data
                 (Value (Offset + 1 .. Offset + Lexicon_Data'Length));

            else
               -- Copy into result, and pad right with spaces
               Result := (others => ' ');
               Result (Lexicon_Data'First .. Value'Length) :=
                 (Value (Offset + 1 .. Offset + Value'Length));

            end if;
      
         end;
         
      end if;
               
      return Result;
         
   end To_Lexicon_Data;
   
   
   nomFumadors : constant Lexicon :=
     (To_Lexicon_Data ("Macia"),
      To_Lexicon_Data ("Xisco"),
      To_Lexicon_Data ("Toni"),
      To_Lexicon_Data ("Laura"),
      To_Lexicon_Data ("Rocky"),
      To_Lexicon_Data ("Paz"),
      To_Lexicon_Data ("Mark"));
     
begin
   --  Insert code here.
   null;
end Main;

如果要证明 AoRTE(即 SparkAda),则函数中 Result 的声明变为

Result : Lexicon_Data
   with Relaxed_Initialization;

..并且该函数To_Lexicon_Data被证明是运行时没有错误的。

请注意 Lexicon 的额外项目 Mark,因为 Lexicon 声明需要 7 个项目才能有效。

评论

0赞 Gneuromante 3/3/2022
这可以使用 Ada.Strings.Fixed.Move 进行简化:en.wikibooks.org/wiki/Ada_Programming/Libraries/...
0赞 Gneuromante 3/3/2022
或者更好的是,使用 Ada.Strings.Fixed.Head。我想我将提供它作为另一个替代答案。
0赞 Gneuromante 3/3/2022 #6

以 Mark 的解决方案为基础,但由于 Ada.Strings.Fixed 的操作而简化。

with Ada.Strings.Fixed;
with Ada.Text_IO;

procedure Main is
   
   subtype Lexicon_Data is String (1 .. 20);
   type Lexicon is array (1 .. 7) of Lexicon_Data;
   
   function To_Lexicon_Data
     (Value : in String)
      return Lexicon_Data
   is
   begin
      return Ada.Strings.Fixed.Head (Value, Lexicon_Data'Length);
   end To_Lexicon_Data;
   
   
   nomFumadors : constant Lexicon :=
     (To_Lexicon_Data ("Macia"),
      To_Lexicon_Data ("Xisco"),
      To_Lexicon_Data ("Toni"),
      To_Lexicon_Data ("Laura"),
      To_Lexicon_Data ("Rocky"),
      To_Lexicon_Data ("Paz"),
      To_Lexicon_Data ("Mark"));
     
begin
   
   for Item of nomFumadors loop
      Ada.Text_IO.Put_Line (Ada.Strings.Fixed.Trim (Item, Ada.Strings.Both));
   end loop;
   
end Main;