Reputation: 41
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
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
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
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
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
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
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