Previous | Table of Contents | Next |
10.4.1.10. Type Composition: Arrays and Records
The next example is a miniature information systems application. A company sells five kind of gadgets, indicated by the colors Red, Blue, Green, Yellow, and Black. In a given time period, a transaction file is created in which a transaction indicates a kind of gadget and a positive (sale) or negative (return) monetary quantity. The program Gadget_Report summarizes the sales, giving, for each of the five gadget types, the number of transactions and the total monetary value. For example, an input transaction file containing
green 56.00 blue 25.00 green 2078.00 black -2065.00
results in this report:
Gadget Type Transactions Value -------------------------------- RED 0 0.00 BLUE 1 25.00 GREEN 2 2134.00 YELLOW 0 0.00 BLACK 1 -2065.00 1 with Ada.Text_IO; 2 with Ada.Integer_Text_IO; 3 with Ada.Float_Text_IO; 4 procedure Gadget_Report is 5 6 subtype Money is 7 Float range -1_000_000_000.00..1_000_000_000.00; 8 9 type Gadgets is (Red, Blue, Green, Yellow, Black); 10 package Gadget_IO is 11 new Ada.Text_IO.Enumeration_IO (Enum => Gadgets); 12 13 type SummaryEntry is record 14 HowMany: Natural := 0; 15 Net : Money := 0.00; 16 end record; 17 18 type Summary is array(Gadgets) of SummaryEntry; 19 20 TodaysSummary : Summary; 21 InputData: Ada.Text_IO.File_Type; 22 WhichKind: Gadgets; 23 Amount: Money; 24 25 begin 26 27 Ada.Text_IO.Open(File => InputData, 28 Mode => Ada.Text_IO.In_File, Name => today.dat); 29 30 while not 31 Ada.Text_IO.End_of_File(File => InputData) loop 32 33 Gadget_IO.Get(File => InputData, Item => WhichKind); 34 Ada.Float_Text_IO.Get 35 (File => InputData, Item => Amount); 36 Ada.Text_IO.Skip_line(File => InputData); 37 38 TodaysSummary(WhichKind).HowMany := 39 TodaysSummary(WhichKind).HowMany + 1; 40 TodaysSummary(WhichKind).Net := 41 TodaysSummary(WhichKind).Net + Amount; 42 43 end loop; 44 45 Ada.Text_IO.Close (File => InputData); 46 47 Ada.Text_IO.Put_Line 48 (Item => Gadget Type Transactions Value); 49 Ada.Text_IO.Put_Line 50 (Item => --------------------------------); 51 52 for WhichKind in Gadgets loop 53 Gadget_IO.Put(Item => WhichKind, Width => 7); 54 Ada.Integer_Text_IO.Put( 55 Item => TodaysSummary(WhichKind).HowMany, 56 Width => 12); 57 Ada.Float_Text_IO.Put( 58 Item => TodaysSummary(WhichKind).Net, 59 Fore => 10, Aft => 2, Exp => 0); 60 Ada.Text_IO.New_Line; 61 end loop; 62 63 end Gadget_Report;
I represent the monetary type as a subtype of the predefined type Float. Line 3 mentions Ada.Float_Text_IO, which allows me to read and write these quantities; lines 6-7 show the subtype declaration. The underscore characters group the digits by threes; they are just used to improve readability.
I declare Gadgets as an enumeration type (line 9). Lines 10-11 constitute a generic instance of the standard generic package Ada.Text_IO.Enumeration_IO. A generic package is a template for a package; in this case, Enumeration_IO is generic because I must supply the name of an enumeration type on whose values input and output is being done. The instance Gadget_IO is capable of reading and writing exactly the five gadget values.
This generic specialization is especially advantageous in reading input values because the input routine (Gadget_IO.Get) validates that an input token in fact belongs to the set of desired values. If the token does not belong to the desired set, the standard exception Ada.Text_IO.Data_Error is raised at the point of the Get call; the exception can be handled by program code, as you shall see in the next example.
In the reporting program, each transaction is read from the input file and the appropriate summariesnumber of transactions and net income per gadget kindare updated. The transaction can then be discarded. To define a summary entry, lines 13-16 declare a record type. A record typein this case, SummaryEntryhas fields or componentsin this case, HowMany and Net; a record type is heterogeneous because in general, each component has its own type. This type declaration creates no objects; it just gives a rule for creating objects from object declarations.
To hold the gadget summaries, line 18 declares an array type Summary. The components of the array are of type SummaryEntry, which illustrates type composition: a programmer-defined array type each of whose elements is a programmer-defined record type. Types can be composed at will in this fashion.
Now, lines 20-23 declare four objects (variables): an array object TodaysSummary, a file object InputData, and two variables to hold the current transaction.
Instead of reading from standard input, this program reads from an external file whose name as seen by the operating system is today.dat. This external file is associated with the file object InputData by the Open call in lines 27-28. The File and Name parameters are obvious; Mode refers to one of the standard sequential file modes In_File, Out_File, and Append_File (an output mode in which writing begins at the end of an existing file). (Adas standard library for direct access files also has an InOut_File mode to open a direct file for both reading and writing).
The main loop of this program (lines 30-43) is straightforward: It reads a transaction from the file and updates the summaries. The expression
TodaysSummary(WhichKind).HowMany
selects the HowMany field of the WhichKind element of the array object TodaysSummary.
Previous | Table of Contents | Next |