Ada语言中遍历Unbounded_String数组并输出数据的实现疑问
Hey there! Let's break down how to solve this problem in Ada, both with straightforward loops and the access type approach you're curious about.
直接遍历数组(简单直观)
If you just need to output the three arrays without worrying about future expansion, the simplest way is to write separate loops for each one. Here's what that looks like in pseudo-Ada code:
with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; procedure Print_All_Data is -- Assume these are your preloaded arrays and counts Days : array (1 .. Days_Total) of Unbounded_String; Months : array (1 .. Months_Total) of Unbounded_String; Seasons : array (1 .. Seasons_Total) of Unbounded_String; begin -- Print Days Put_Line("Days:"); for I in 1 .. Days_Total loop Put_Line(To_String(Days(I))); end loop; -- Print Months Put_Line(ASCII.LF & "Months:"); for I in 1 .. Months_Total loop Put_Line(To_String(Months(I))); end loop; -- Print Seasons Put_Line(ASCII.LF & "Seasons:"); for I in 1 .. Seasons_Total loop Put_Line(To_String(Seasons(I))); end loop; end Print_All_Data;
This approach is easy to read and implement, but it repeats code—if you add more arrays later, you'll have to write another loop each time. That's where access types come in handy for creating a reusable solution.
使用访问类型实现通用遍历(可扩展)
To avoid repeating code, you can define a generic procedure that works with any Unbounded_String array using access types. Here's how to set that up:
Step 1: Define shared types
First, create a generic array type and its corresponding access type to standardize how we reference the arrays:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package Array_Types is -- Generic array of Unbounded_String type Unbounded_String_Array is array (Positive range <>) of Unbounded_String; -- Access type for the array type Unbounded_String_Array_Access is access Unbounded_String_Array; end Array_Types;
Step 2: Create a reusable print procedure
Next, write a generic procedure that takes an array access and element count, then prints all elements:
with Ada.Text_IO; use Ada.Text_IO; with Array_Types; use Array_Types; generic Element_Count : Positive; procedure Generic_Print_Array(Arr : Unbounded_String_Array_Access); procedure Generic_Print_Array(Arr : Unbounded_String_Array_Access) is begin for I in 1 .. Element_Count loop Put_Line(To_String(Arr(I))); end loop; end Generic_Print_Array;
Step 3: Instantiate and use the procedure
Now you can instantiate the generic procedure for each of your arrays, then call them to output the data:
with Ada.Text_IO; use Ada.Text_IO; with Array_Types; use Array_Types; with Generic_Print_Array; procedure Print_All_Data is -- Preloaded arrays and counts Days : Unbounded_String_Array(1 .. Days_Total); Months : Unbounded_String_Array(1 .. Months_Total); Seasons : Unbounded_String_Array(1 .. Seasons_Total); -- Instantiate the print procedure for each array procedure Print_Days is new Generic_Print_Array(Element_Count => Days_Total); procedure Print_Months is new Generic_Print_Array(Element_Count => Months_Total); procedure Print_Seasons is new Generic_Print_Array(Element_Count => Seasons_Total); begin Put_Line("Days:"); Print_Days(Days'Access); -- Pass the array's access using 'Access attribute Put_Line(ASCII.LF & "Months:"); Print_Months(Months'Access); Put_Line(ASCII.LF & "Seasons:"); Print_Seasons(Seasons'Access); end Print_All_Data;
Alternative: Use a record to bundle data
If you want even more flexibility, you can bundle the array access and element count into a record, then write a single procedure to handle this record:
with Ada.Text_IO; use Ada.Text_IO; with Array_Types; use Array_Types; procedure Print_All_Data is type Array_Metadata is record Arr_Access : Unbounded_String_Array_Access; Count : Positive; end record; procedure Print_Array(Data : Array_Metadata) is begin for I in 1 .. Data.Count loop Put_Line(To_String(Data.Arr_Access(I))); end loop; end Print_Array; -- Bundle your arrays and counts Days_Data : Array_Metadata := (Arr_Access => Days'Access, Count => Days_Total); Months_Data : Array_Metadata := (Arr_Access => Months'Access, Count => Months_Total); Seasons_Data : Array_Metadata := (Arr_Access => Seasons'Access, Count => Seasons_Total); begin Put_Line("Days:"); Print_Array(Days_Data); Put_Line(ASCII.LF & "Months:"); Print_Array(Months_Data); Put_Line(ASCII.LF & "Seasons:"); Print_Array(Seasons_Data); end Print_All_Data;
Key note about access types
When using 'Access to get an array's access type, make sure the array's lifetime is longer than the access type's usage. If your arrays are declared at the package level or as global variables, this isn't an issue. If they're local to a procedure, ensure the access type doesn't outlive the array (to avoid dangling references).
内容的提问来源于stack exchange,提问作者commandlinegamer

