既然这有功课的感觉,那么一个过于复杂、过于笼统的例子呢?一切正常,除了随机化,这是留给读者的练习。
Test_Table.adb
With
Tabling,
Ada.Streams.Stream_IO,
Ada.Text_IO.Text_Streams;
Use
Ada.Text_IO;
Procedure Test_Table is
-- Here we declare a stream and associate it with the standard-output,
-- this can easily be altered to any file. Yay streams!
Output : Access Ada.Streams.Root_Stream_Type:=
Ada.Text_IO.Text_Streams.Stream( Standard_Output );
Package test is new Tabling( Rows => 40, Cols => 80 );
temp : test.Table;
Begin
-- A single line to write the table.
Test.Table'Write( Output, temp );
New_Line;
End Test_Tables;
现在是不是很好很简单?好吧,这里是过于复杂和过于笼统的部分:规范和实现!
Tabling.ads
Pragma Ada_2012;
With Ada.Streams;
Generic
Rows : Positive := 3;
Cols : Positive := 4;
Package Tabling is
-- Tables with rows or columns exceeding 200 are absurd, so we disallow them.
Maximum : constant:= 200;
Pragma Assert (Rows <= Maximum and Cols <= Maximum);
-- Table is a private entity.
Type Table is private;
-- Forward declaring the rows and columns here.
Type Col is private;
Type Row is private;
Private
Use Ada.Streams;
-- We are defining a type with elements of 'V' or 'M'.
Type Element_Type is ( 'M', 'V' );
-- We are declaring a stream writing function.
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Element_Type);
-- We are overriding the default write function with the one we defined.
For Element_Type'Write use Write;
-- Because we don't want an allocation wrror we restrict index-ranges to
-- a more reasonable value.
SubType Short_Positive is Positive Range Positive'First..Maximum;
-- We create subtypes representing the ranges that Rows or Columns take.
subtype column_index is Short_Positive Range Positive'First..Cols;
subtype row_index is Short_Positive Range Positive'First..Rows;
-- Here we define stream-writing functions for rows and columns.
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Col);
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Row);
-- Here we override the stream-writing methods for rows and columns.
For Col'Write Use Write;
For Row'Write Use Write;
-- Here we finally define Rows and Columns.
Type Col is Array(column_index)of Element_Type;
Type Row is Array( row_index ) of Col;
-- THIS IS A STUB, SUBSTITUTED FOR YOUR CALL TO RANDOM.
Function RANDOM_CALL Return Element_Type is ( 'M' );
-- Finally we define the stream-writing for a table...
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Table);
-- and define what a table is...
Type Table is record
Data : Row:= ( others => (others => RANDOM_CALL) );
end record;
-- finishing off by assigning our write function to the type.
For Table'Write Use Write;
End Tabling;
Tabling.adb
package body Tabling is
-- Quick definition of the new-line, windows-style.
New_Line : Constant String:= ASCII.CR & ASCII.LF;
-- Implementations of our stream writing functions.
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Element_Type) is
-- Convert takes the element-type and transforms it into a character.
Function Convert (Input : Element_Type:= Item) Return Character is
begin
-- A simple mapping using case, it also has the advantage of raising
-- a compiler error should the valuse "Element_Type" can take change.
case Input is
when 'M' => return 'm';
when 'V' => return 'v';
end case;
end Convert;
begin
Character'Write( Stream, Convert );
end Write;
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Col) is
begin
-- Using the new-style for-loop, we iterate over the given columns,
-- taking care to wrap the elements in the table's cell-definition tag.
for Element of Item loop
String'Write( Stream, ASCII.HT & "<td>" );
Element_Type'Write( Stream, Element );
String'Write( Stream, "</td>" & New_Line );
end loop;
end Write;
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Row) is
begin
-- Using the new-style loop, we iterate through the row, wrapping each
-- in the table-row tag, <tr>.
for Element of Item loop
String'Write( Stream, "<tr>" & New_Line);
col'Write( Stream, Element );
String'Write( Stream, "</tr>" & New_Line);
end loop;
end Write;
Procedure Write(
Stream : access Root_Stream_Type'Class;
Item : in Table) is
begin
-- Start the table.
String'Write(Stream, "<Table>" & New_Line);
-- Write out the rows.
Row'Write (Stream, Item.Data );
-- End the table.
String'Write(Stream, "</Table>");
end Write;
End Tabling;