1

I have loaded some data from a file into three arrays of type Unbounded_String, which I'll call Days, Months, and Seasons.

Each of these arrays has a corresponding Integer which has recorded the number of items in the array, viz. Days_Total, Months_Total, and Seasons_Total.

I'd like to iterate through the three arrays, and output all the data, ideally something of the form (and this is pseudo-Ada):

for Count_1 in (Days, Months, Years) loop
  for Count_2 in 1 .. (Count_1)_Total loop
      Put_Line (Count_1 (Count_2));
  end loop;
end loop;

Whereas what I'm actually doing at the moment is

for Count in 1 .. Days_Total loop
   Put_Line (Days (Count));
end loop;

for Count in 1 .. Months_Total loop
   Put_Line (Months (Count));
end loop;

for Count in 1 .. Seasons_Total loop
   Put_Line (Seasons (Count));
end loop;

I'm guessing I need to use an Access Type, but at the moment am having trouble getting my round it. The full example program is (load_data_example.adb):

with Ada.Strings.Unbounded, Text_IO, Ustrings;
use  Ada.Strings.Unbounded, Text_IO, Ustrings;




procedure Load_Data_Example is



   Max_Items                   : Constant := 12;
   Datafile                    : File_Type;
   Datafile_Name               : String := "datafile";

   type Small_String_Array is array (1 .. Max_Items)
     of Unbounded_String;

   Days, Months, Seasons       : Small_String_Array;
   Days_Total, Months_Total    : Integer := 0;
   Seasons_Total               : Integer := 0;
   Datafile_Len, Datafile_Skip : Integer := 0;
   Line_Count, Lines_Expected  : Integer := 0;
   Data_Index, Input_Len       : Integer := 0;
   Input                       : Unbounded_String;



begin


    Open (Datafile, In_File, Datafile_Name);

    while (not End_Of_File (Datafile)) loop

       Get_Line (Datafile, Input);
       Datafile_Len := Datafile_Len + 1;
       Input_Len := Length (Input);

       if Line_Count <= (Lines_Expected - 1) then

          Line_Count := Line_Count + 1;

       end if;

       if Datafile_Len = (Datafile_Skip + 1) then

          Line_Count := 0;
          Data_Index := Data_Index + 1;
          Lines_Expected := Integer'Value (To_String (Input));
          Datafile_Skip := Datafile_Skip + Lines_Expected + 1;

       else

          case Data_Index is

             when      1  =>  Days (Line_Count) := Input;
                              Days_Total := Days_Total + 1;

             when      2  =>  Months (Line_Count) := Input;
                              Months_Total := Months_Total + 1;

             when      3  =>  Seasons (Line_Count) := Input;
                              Seasons_Total := Seasons_Total + 1;

             when others  =>  null;

          end case;

       end if;

    end loop;

    Close (Datafile);


    for Count in 1 .. Days_Total loop
       Put_Line (Days (Count));
    end loop;

    for Count in 1 .. Months_Total loop
       Put_Line (Months (Count));
    end loop;

    for Count in 1 .. Seasons_Total loop
       Put_Line (Seasons (Count));
    end loop;


end Load_Data_Example;

And the datafile is:

3
Monday
Tuesday
Friday
4
April
June
August
September
2
Spring
Winter

Any hints would be really appreciated.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

2 Answers2

4

One approach: collect everything about each case in a record, and build an array of those records you can sequence over.

type Item_List is record
   Total : natural;
   Names : Small_String_Array;
end record;

type Categories is (Days, Months, Seasons);

Items : array (Categories) of Item_List;

for Count_1 in Categories loop
  for Count_2 in 1 .. Items(Count_1).Total loop
      Put_Line (Items(Count_1).Names(Count_2));
  end loop;
end loop;
Jacob Sparre Andersen
  • 6,733
  • 17
  • 22
3

Expanding on Brian's answer: In Ada 2012, you have containers that implement bounded vectors like those you use. Instead of taking care of incrementing and checking the total yourself, you can use those:

   package String_Vectors is new Ada.Containers.Bounded_Vectors
     (Positive, Unbounded_String);
   type Categories is (Days, Months, Seasons);
   Items : array (Categories) of String_Vectors.Vector (12);

begin
   --  ... other code here

   for Catogory in Categories loop
      for Item of Items (Category) loop
         --  using Ada 2012 iterators in this for loop.
         --  only yields the items that have actually been appended
         --  to the vector.

         Put_Line (Item);
      end loop;
   end loop;
flyx
  • 35,506
  • 7
  • 89
  • 126
  • Looks interesting, I'll check that out. Thanks very much. – commandlinegamer Mar 08 '18 at 23:51
  • If one of the answers provided was ok, please check it as a good answer. If you do not, I fear that nobody ill answer your questions any more. StackOverflow runs with reputation points won by answering questions. So if you don't give points by marking correct answers or don't give points on answers, you won't get answers – Frédéric Praca Jan 17 '19 at 08:53