Macia Salva
Macia Salva

Reputation: 41

How can I define an Array of Strings in Ada?

What I want is to define an array of Strings in Ada.

I'm trying to execute this code:

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");

And the compiler says:

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

My line 42 is this:

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

But compailer says the warning is in line 43 and 44: what are these:

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

Can somebody help me with that?

Upvotes: 3

Views: 943

Answers (6)

Gneuromante
Gneuromante

Reputation: 614

Building upon the solution by Mark, but simplifying thanks to the operations from 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;

Upvotes: 0

Mark
Mark

Reputation: 153

Similar to Jeff Carter's answer, but using a function to coerce any string into a fixed string ...

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;

If you wanted to prove AoRTE (ie SparkAda) then the declaration for Result in the function becomes

Result : Lexicon_Data
   with Relaxed_Initialization;

.. and the function To_Lexicon_Data is proved as being runtime error free.

Note the extra item for Lexicon, Mark, since you need seven items for the Lexicon declaration to be valid.

Upvotes: 0

Jeffrey R. Carter
Jeffrey R. Carter

Reputation: 3358

Another solution is to use String, truncate long strings, and pad short strings:

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"), ...

Upvotes: 1

Jere
Jere

Reputation: 3641

Others have mentioned bounded and unbounded strings. You can also use Indefinite_Vectors. You can use the "&" operator to initialize them (as opposed to the initializer list though the next version of Ada is adding initializer lists to containers). You can use a vector just like an array by passing indexes in plus you get a lot of other additional functionality.

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;

Upvotes: 6

Zerte
Zerte

Reputation: 1516

Another option is Unbounded_String (as its name suggests, length is variable and unlimited):

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;

Upvotes: 5

flyx
flyx

Reputation: 39638

You declared your array to hold Strings of length 20. The String literals you give are less than 20 Characters long. Hence the error.

You seem to be looking for a string type that contains a maximum of 20 characters. This is provided in 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"));

To get back a String from a Bounded_String, use e.g. To_String (Lexicon (2)).

Upvotes: 5

Related Questions