Unable to print the contents of an Array String of String Constants?

Viewed 154

I'm a bit of a beginner when it comes to Ada, and I'm trying to declare and use an array of strings of different lengths.

Using Ada'83 I can declare an array of variable length string constants as follows (example taken from the Ada FAQ)

type table is access String;

 TESTS : constant array (Positive range 1..3) of table
         := ( 1 => new String'("One"),
              2 => new String'("Two"),
              3 => new String'("Three")
            );

However much to my frustration even though the result appears to be an array of character arrays they don't behave as strings. When I try to compile the following code I get an error message 'Inconsistency detected during overload resolution [LRM 8.7]'

for COUNT in TESTS'Range loop
   Put(TESTS(COUNT));
   New_Line;
end loop;

However, I can print out the content of each of the 'strings' using the following code.

for COUNT in TEST'Range loop
   for COUNTER in TEST(COUNT)'Range loop
      Put(TEST(COUNT)(COUNTER));
   end loop;
   New_Line;
end loop;

Unfortunately I want to use the values to test some code that takes a string as a parameter, so this doesn't really help...

Is there a way to be to iterate over an array of string constants of varying length in Ada'83, or to convert the character arrays into strings of varying length.

Thanks

No, this isn't homework, and yes, I know I'm using an ancient compiler!

3 Answers

Test is undefined; I'll presume you mean Tests.

Table is not a string type; it is an access type. To reference the value that an access value designates, one uses .all:

Tests (Tests'First).all

is a string. Ada contains some shortcuts for access-to-array types to make them easier to use, allowing .all to be left off before attributes and indexing, which is why Tests (Count)'Range and Tests (Count) (Counter) work. To reference the whole value, though, .all is required:

Text_IO.Put_Line (Item => Tests (Counter).all);

However, a better approach would be to define a variable-length string abstraction and use that instead of an access type.

Thank you that works a treat - however, how would I go about defining 'a variable-length string abstraction' to do the same job?

Use private-types + access-types, perhaps like the following:

Package String_Abstraction is
    
    Type DString is private;
    Function "+"( Right : DString ) return  String;
    Function "+"( Right :  String ) return DString;
    Function "&"( Left, Right : String ) return DString;
    --...
Private
    Type Data(<>);
    Type DString is access Data;
End String_Abstraction;

with implementation of:

Package Body String_Abstraction is
    Type Data( Length : Natural ) is record
        Text : String(1..Length) := (others => ASCII.NUL);
    end record;
    
    Function "+"( Right : String ) return DString is
    Begin
        Return New Data'( Text => Right, Length => Right'Length );
    End "+";
    
    Function "&"( Left, Right : String ) return DString is
    Begin
        Return +(Left & Right);
    End "&";
    
    Function "+"( Right : DString ) return  String is
    Begin
        Return Right.Text;
    End "+";
    
    --...
End String_Abstraction;

Which could be used as follows:

Table : Constant Array(Positive range <>) of String_Abstraction.DString:=
  ( String_Abstraction."+"( "This" ),
    String_Abstraction."+"( "EXAMPLE" ),
    String_Abstraction."+"( "list" ),
    String_Abstraction."+"( "exists." )
  );

and

Print_Table:
For Index in Table'Range Loop
    Declare
        Use String_Abstraction;
        Item : DString renames Table(Index);
    Begin
        Ada.Text_IO.Put_Line( +Item );
    End;
End loop Print_Table;

If you had a use prior to the declaration of table, you could have:

Use String_Abstraction;
Table : Constant Array(Positive range <>) of String_Abstraction.DString:=
  ( +"This",
    +"EXAMPLE",
    +"list",
    +"exists."
  );

It's certainly not complete, but that gives you the basic idea of how to do it.

GNAT Studio Community Edition is free to use for freelance use and hobby going coders. It comes pre-installed with a decent Ada 2012 compiler. I had to also install a small add on called Ada GDE to get the code to run.

If your looking for an up to date book to study from, I highly recommend Ada 2012 by john Barnes. It's a bit of a beast at over 900 pages long, but he goes into good detail on concepts and provides plenty of sample code to help. He also wrote one for Ada 95 I believe.

Related