In my printf library, I offer an option to print a container's items.
Here is a description.
R
Using AEL Printf Routines
The AEL Printf routines provide a means by which to format strings in a manner
reminiscent of, but not strictly duplicating, the traditional printf functions
in C.
Format string construction (in order):
%
[<decoration_flag>]
[<agent_flag>]
[<alignment_flag>]
[<fill_specifier>]
[<field_width>]
<field_type>
Where:
The ‘%’ character denotes a format specifier, as it does in C printf.
The ‘%’ character is also Eiffel’s escape character. As such, when
creating a format string, be sure either to use a verbatim string, or
to add another ‘%’ character before each format specifier, lest Eiffel
treat it as an escape character.
For example, "name=%s", if not a verbatim string, will be interpreted
by Eiffel as an attempt to use ‘s’ as a character code, and because ‘s’
is not an Eiffel character code, the compiler will flag it as a syntax
error.
To compensate, simply double up the ‘%’ characters. The successful form
would then be "name=%%s".
When using verbatim strings, Eiffel does not interpret the ‘%’ character,
and so only a single ‘%’ is needed in that case.
"{
name=%s
}"
And Where:
<decoration_flag> ::= '#'
Decoration (triggered by the decoration flag) consumes part of the field
width.
Decoration is applied as follows:
"0x" preceding hexadecimal values
"0" preceding octal values
"b" following binary values
Delimiters between thousands for decimal values (commas by default)
Newline between list values (See ‘L’ field type, below)
Examples:
printf (“%%#10x”, << 123 >>)
yields:
0x0000007B
printf (“%%#10o”, << 123 >>)
yields:
0000000173
printf (“%%#10b”, << 123 >>)
yields:
001111011b
printf (“%%#10d”, << 1230 >>)
yields:
1,230
printf (“%%#L”, << << 1, 2, 3 >> >>)
yields:
1
2
3
And Where:
<agent_flag> ::= '~'
Valid for List (%L), Matrix (%M), and Table (%H) formats only.
Cannot be combined with decoration flag (and is ignored in that case).
Example (List format):
printf (“%%~L”, << << 1, 2, 3 >>, agent item_out >>)
yields:
1 2 4
In the case where ‘item_out’ is a FUNCTION that produces
10-character-wide fields of right-justified decimal numbers
And Where:
<alignment_flag> ::= '-' | '=' | '+'
Specifies left, center, or right alignment, respectively
Valid for String and numeric formats.
When ‘+’ is applied to Matrix format, forces column-major output
(row-major is default).
And Where:
<fill_specifier> ::= <character>
Fills remainder of field width with given character (default is blank)
And Where:
<field_width> ::= <simple_width> | <complex_width>
<field_type> ::= <character>
Field types include the following:
A denotes an Agent expression.
Argument must be a function that accepts an argument of type ANY
and returns a STRING.
a denotes an ANY expression.
Argument is untyped and the output is <arg>.out.
B denotes a Boolean expression
This shows as "True" or "False"
A global flag, for the AEL Printf subsystem, can be set to change
BOOLEAN values to all lower case (“true” or “false”), as needed for
some protocols. See Shared Printf Settings, below.
b denotes a Binary integer expression
This shows as ones and zeroes.
If no field width is specified, the field width will be the smallest
whole integer size (8, 16, 32, 64) that can hold the value of the
argument. Values from 0 through 255 have an implicit field width
of 8, values between 256 and 65535 have 16, values between 65536
and 4294967295 have 32, and larger values have an implicit field
width of 64.
When a field width is specified, the default padding character is blank.
A ‘0’ padding character can also be specified (as with other integral
types) for positive values, but when the value being rendered is
negative, the pad character used is a ‘1’.
C denotes a Complex expression, enabling formatted output of a container
and its items, and having the form:
"%C(" <container_fmt> [ <sub_fmt> ] ')'
<container_fmt> ::= List, Matrix or Table std syntax
<sub_fmt> ::= '[' <fmt> "][" <fmt_args> ']'
<fmt> ::= per-item format string, std syntax
<fmt_args> ::= <tags> (position-relative, unseparated)
<tags> ::= <tag> [<tags>]
<tag> ::= V | I | K | R | C
Where:
V=item value (all containers)
I=item position (List and Table)
K=item key (Hash Table only)
R=item row (Matrix only)
C=item column (Matrix only)
Examples:
%C(#L[%-4d: %+16s][IV])
%C(+M[(%04d,%04d) %+16s][CRV])
%C(,H[%a (by %s, at %d)][VKI])
%C(L)
c denotes a single CHARACTER
d denotes a Decimal integer expression
Type specifier can be preceded by a delimiter character with which
to separate groups of 3 adjacent digits (thousands).
Alignment characters cannot be used as delimiters.
f denotes a Floating Point (REAL_* or DOUBLE) expression
Field width for floating point values are given in the form:
<overall_width>"."<right_width>
Where <overall_width> is the minimum width of the entire representation,
and <right_width> is the width for the fractional part (precision).
A precision of 0 results in a whole number representation, without
decimal point (effectively rounding to integer).
H denotes a (Hash) Table expression
Type specifier can be preceded by a delimiter character with which to
separate items (default is blank).
Alignment characters cannot be used as delimiters.
In place of a delimiter, the agent flag ('~') can be used. In that
case, the argument must be a TUPLE [HASH_TABLE, FUNCTION] instead of
a container alone.
Note that hash tables can be used as arguments to List formats.
The Complex expression is preferred for outputing hash table contents
when the desire is to include the per-item key.
L denotes a List-like expression (any FINITE container)
Type specifier can be preceded by a delimiter character with which
to separate list items (default is blank).
Alignment characters cannot be used as delimiters.
In place of a delimiter, the agent flag ('~') can be used. In that
case, the argument must be a TUPLE [CONTAINER, FUNCTION] instead of
a container alone.
Because newline characters (‘%N’) in Eiffel include escape characters,
it is not possible to use the newline character as a delimiter (“%%NL”).
Eiffel interprets that sequence as an escaped percent sign, followed
by “NL”.
There is, however, a way to accomplish the same thing. By specifying
the format as “%#L”, the '#' character is interpreted as requesting
newline-separated items (the default decoration for LIST-like formats).
It is also possible to specify a delimiter character to precede each
newline by including the delimiter character between the ‘#’ character
and the ‘L’ character in the format string (e.g. “%%#,L).
Example:
printf (“%%#,L”, << << 1, 2, 3 >> >>)
yields:
1,
2,
3
Specifying the delimiter between the percent character and the ‘L”,
without the ‘#’ character, will insert the delimiter character between
elements of the container in the output, and will not insert newlines.
Example:
printf (“%%,L”, << << 1, 2, 3 >> >>)
yields:
1,2,3
M denotes a Matrix expression (an ARRAY2)
Type specifier can be preceded by a delimiter character with which to
separate items (default is blank). Using ‘,’ as a separator produces
a CSV format.
Alignment characters cannot be used as delimiters.
The ‘+’ alignment character, when used, creates column-at-a-time output
(default is row-at-a-time).
In place of a delimiter, the agent flag ('~') can be used. In that
case, the argument must be a TUPLE [ARRAY2, FUNCTION] instead of
a container alone.
In row-major format, newlines separate rows. In column-major format,
newlines separate columns.
Example:
my_matrix contents:
11 12 13 -- Row 1, columns 1-3
21 22 23 -- Row 2, columns 1-3
printf (“%%,M”, << my_matrix >>)
yields:
11,12,13
21,22,23
o denotes an Octal INTEGER expression
P denotes an Percent expression (float value multiplied by 100 and
followed by a percent symbol)
s denotes character STRING
u denotes a NATURAL (unsigned Decimal integer) expression
x denotes a Hexadecimal INTEGER expression
In use, a class calls one of the AEL Printf routines with at least a format
string and an argument list.
The argument list can be an object of any type, but for expected behavior,
there are a few restrictions.
o When the format string has no format specifiers, then the argument list can
be an empty manifest ARRAY, and empty TUPLE, or an explicit Void.
Example: printf (“This has no format specifiers”, Void)
Example: printf (“This has no format specifiers”, << >>)
Example: printf (“This has no format specifiers”, [])
o When the format string contains a single format specifier, then the
argument list can be either a container with a single item of a type
conforming to the single format specifier, or an object of a type
conforming to the single format specifier.
Example: printf (“This has %%d format specifier”, 1)
Example: printf (“This has %%d format specifier”, << 1 >>)
o When the format string contains multiple format specifiers, then the
argument list must be either a TUPLE or a proper descendent of FINITE [ANY],
in which each item, related by position to its corresponding format
specifier, has a type conforming to its corresponding format specifier.
Example:
printf (“This has %%s (%%d) format specifiers”, << ”multiple”, 2 >>)