Reputation: 111
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.
Upvotes: 1
Views: 1127
Reputation: 39638
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;
Upvotes: 3
Reputation:
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;
Upvotes: 4