Reputation: 1343
I have a string lx : String
that I want to set the value for later on in my code, but I'm getting error unconstrained subtype not allowed (need initialization) provide initial value or explicit array bounds
I also have a string array L_array : array (1 .. user_size) of String;
, which is throwing error unconstrained element type in array declaration
. I can't initialize this to begin with, as the values are read in from a text file. What should I do about this if I want to set these values later?
Upvotes: 2
Views: 2141
Reputation:
There are two questions here really, but with the same underlying cause : a String
must have its size fixed (i.e. constrained) when it is created.
If you know its size, and (in the case of the array of String
) all String
s are the same size, constraining them is easy and needs no further comment.
Think about what String
s of unknown length implies : unknown storage requirements. One approach is to use pointers or access types, allocate storage to hold the string, and remember to free it later. That way, as in other languages, has the potential for bugs, memory leaks etc. So does the alternative approach of guessing an upper limit for the size, which opens the potential for buffer overflows. You can do it in Ada, as in other languages, but ... not best practice.
Ada provides abstractions over both these patterns, in the form of Unbounded_String
and Bounded_String
respectively which aim to minimise the problems. But they are still less convenient in use than String
.
There's a somewhat intense discussion of these abstractions on the comp.lang.ada newsgroup (my apologies for using the Google Groups gateway to it)
So I'll suggest ways you can do these two tasks just with String
.
For the case of a single string lx : String
where you set the value later on, the answer is simple : just declare the String
later on, initialised with that value. Instead of
lx : String;
...
lx := Read(My_File);
Process_String(lx);
use a declare block (typically in a loop body):
...
declare
lx : String := Read(My_File);
begin
Process_String(lx);
end;
At end
the string lx
goes out of scope, and it is created anew (with the correct size, from the initialisation, next time you reach the declare
block.
An Array of String
is more difficult if each member has a different size, and Bounded_String
or Unbounded_String
are useful candidates.
But an alternative approach (since Ada-2005) would be to use the Ada.Containers
package instead of an Array. These come in Definite and Indefinite flavours, you want an Indefinite container to store members of different sizes. Specifically Ada.Containers.Indefinite_Vectors
as a Vector can be indexed similar to an Array.
This approach has similarities to using std_vector
in C++, in fact the Standard Template Library was originally for Ada, and was later adapted to C++.
Prior to Ada-2005, Ada.Containers
was not part of the language but you'd use an equivalent from an external library such as (I think) the Booch Components (Grady Booch).
A starter :
with Ada.Containers.Indefinite_Vectors;
with Ada.Text_IO;
procedure String_Vector is
User_Size : constant natural := 10;
subtype Index is natural range 1 .. User_Size;
-- Indefinite_Vectors is a generic package.
-- You can't use it directly, instantiate it with index and content types
package String_Holder is new Ada.Containers.Indefinite_Vectors(Index,String);
-- make String_Holder operations visible
use String_Holder;
LV : String_Holder.Vector; -- initially empty
L_Vector : String_Holder.Vector := -- initialise to size with empty elements
To_Vector(Ada.Containers.Count_Type(User_Size));
begin
L_Vector.Replace_Element(1,"hello");
LV.Append("world");
Ada.Text_IO.Put_Line(L_Vector(1) & " " & LV(1));
end String_Vector;
Upvotes: 7
Reputation: 418
Ada's String type is defined as
type String is array(Positive range <>) of Character
. Which needs an initial range to declare an variable, by either given an initial string or given a range constraint, otherwise compiler won't be able to know how large will the object be.
Take a look at the sample at Rosettacode for how to read from a file.
Upvotes: 3