Jaken
Jaken

Reputation: 1343

Why do strings need to be initialized with an initial value?

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

Answers (2)

user1818839
user1818839

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 Strings are the same size, constraining them is easy and needs no further comment.

Think about what Strings 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

qunying
qunying

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

Related Questions