Ada String Handling
I am trying to define an array of strings in Ada to store variable sized strings. The problem is that I have to pre-determine the size of my strings, which I don't know at compile time, and with Unbounded_Strings the String_Split.Create won't work as it requires Standard.String.
Below is my code where I need to parse variable sized strings, not just fixed length 4.
Thanks in advance.
type StrArray is array(1..7) of String(1..4);
function Split(Line : String;Sep : String) return StrArray is
Tokens : String_Split.Slice_Set;
Output : StrArray;
Count : Natural := 0;
begin
String_Split.Create(s => Tokens,
From => Line,
Separators => Sep,
Mode => String_Split.Single);
For I in 1 .. String_Split.Slice_Count (Tokens) loop
Count := Count + 1;
Output(Count) := String_Split.Slice(Tokens,I); -- Not sure how to convert Slice_Count to Integer either!
end loop;
return Output;
end Split;
source to share
The fact that it GNAT.String_Split
uses String
doesn't mean that yours StrArray
should. And you need to serve input strings with varying numbers of tokens, so start by declaring StrArray
as an unbounded array type:
type StrArray is array (Positive range <>)
of Ada.Strings.Unbounded.Unbounded_String;
Now it Split
starts like this:
function Split (Line : String; Sep : String) return StrArray is
Tokens : GNAT.String_Split.Slice_Set;
begin
(we won't announce it yet Output
, and we won't need it Count
, and I had to google to find out what String_Split
is the GNAT utility package).
The first thing to do is split the input string so we know how big it should be Output
(by the way, do you really want to Single
?):
GNAT.String_Split.Create (S => Tokens, From => Line, Separators => Sep, Mode => GNAT.String_Split.Single);
Now we can declare Output
with Slice_Count
. Note the conversion to Natural
(not Positive
; if the input is empty, there will be no tokens, so the output will be an empty array, range 1 .. 0
).
declare
Output : StrArray
(1 .. Natural (GNAT.String_Split.Slice_Count (Tokens)));
begin
Now fill with Output
tokens. AdaCore decided to implement Slice_Number
as new Natural
, not as a subtype Natural
, so we need a transformation.
for I in Output'Range loop
Output (I) :=
Ada.Strings.Unbounded.To_Unbounded_String
(GNAT.String_Split.Slice
(Tokens, GNAT.String_Split.Slice_Number (I)));
end loop;
... and return Output
to the ad block.
return Output;
end;
end Split;
To call Split
that will return the StrArray
length of which you don't know in advance, you can use the start-value constraint technique :
declare
T : constant StrArray := Split ("goodbye world ", " ");
begin
for J in T'Range loop
Ada.Text_IO.Put_Line ("'"
& Ada.Strings.Unbounded.To_String (T (J))
& "'");
end loop;
end;
source to share