ZetCode

Algol 68 formatted transput

last modified November 13, 2026

Formatted transput is part of the Algol 68 language rather than a library. A program writes a format denotation between dollar signs, and the frames inside it say how each value is laid out: its width, its decimals, its sign, and the text between the values. This article describes the format denotation, the frames that print numbers and strings, the replicators, and the procedures that turn a value into a string.

Format denotations

A format denotation is a value of mode FORMAT written between two dollar signs. It mixes literal text in quotes with frames such as g and a, and printf takes the format first and the values afterwards.

format.a68
BEGIN
  printf(($"Name: "3a", age: "g(0)$, "Ada", 36));
  print((newline))
END

The quoted parts are copied to the output and the two frames take one value each, in the order of the value list. 3a is a string frame three characters wide, and g(0) is a general frame without padding, which prints the integer 36 as two digits.

$ a68g format.a68
Name: Ada, age: 36

Width and decimals with g

The g frame prints a number in a field of a given width. The first parameter is the width, and a negative width means that the value is right justified without a sign; a second parameter gives the number of decimals of a real.

widths.a68
BEGIN
  printf(($"["g(8)"]"$, 42));
  print((newline));
  printf(($"["g(-8)"]"$, 42));
  print((newline));
  printf(($"["g(10,2)"]"$, 3.14159));
  print((newline));
  printf(($"["g(-10,2)"]"$, -3.14159));
  print((newline))
END

A positive width leaves room for the sign and right justifies the value, so 42 appears with a plus sign and five spaces in front of it. A negative width drops the sign and right justifies the digits, which is why the second line has one more space before them. The decimals of the last two lines are rounded to two places, and a negative value keeps its minus sign inside the field.

$ a68g widths.a68
[     +42]
[      42]
[     +3.14]
[     -3.14]

Integral fields with d

The d frame prints an integer without a point. Its width is a minimum, and a short value is padded with zeros, not with spaces. A sign mould written in front of the width adds a sign in every case, including the plus.

ints.a68
BEGIN
  printf(($"["5d"]"$, 42));
  print((newline));
  printf(($"["-5d"]"$, -42));
  print((newline));
  printf(($"["+5d"]"$, 42));
  print((newline));
  printf(($"["-5d"]"$, 42));
  print((newline));
  printf(($"["8d"]"$, 4711));
  print((newline))
END

The first line shows the zero filling: 42 becomes 00042. A sign mould reserves the place for the sign before the digits, so the second line keeps the minus of the value and fills the rest with zeros. A plus mould writes a plus even for a positive value, and a minus mould leaves a blank in that place instead, which gives the fourth line its leading space.

$ a68g ints.a68
[00042]
[-00042]
[+00042]
[ 00042]
[00004711]

Fields that are too narrow

A frame reserves a fixed number of characters. When the value needs more room than the frame offers, the general frame replaces the value with asterisks, so a broken table is visible instead of silently shifted.

narrow.a68
BEGIN
  printf(($"["g(6)"]"$, 42));
  print((newline));
  printf(($"["g(3)"]"$, 42));
  print((newline));
  printf(($"["g(2)"]"$, 12345));
  print((newline))
END

Six characters are enough for the sign and the two digits, and so are three. The last call asks for two characters for a five digit number, and the frame answers with two asterisks. The d frame is stricter: an integer that does not fit raises a runtime error instead of printing asterisks.

$ a68g narrow.a68
[   +42]
[+42]
[**]

String fields with a

The a frame inserts a string. Unlike a number frame, its width must equal the number of characters of the value, because the frame declares a string of exactly that length rather than a field to pad.

strings.a68
BEGIN
  printf(($"["2a"]"$, "ab"));
  print((newline));
  printf(($"["3a"]"$, "abc"));
  print((newline))
END

Both calls match the width and the value, so both succeed. A wider frame with a shorter string, as in 5a with "ab", is a runtime error about transputting a character row, and a shorter frame with a longer string fails in the same way. To align text in a table, the program builds the spaces itself or uses literal text inside the format.

$ a68g strings.a68
[ab]
[abc]

Replicators

A number in front of a parenthesised group of format items repeats that group, and a string inside the group is repeated as text. This is how a format draws a line of dashes or pads a column without writing the characters out.

replicas.a68
BEGIN
  printf(($10("-")$));
  print((newline));
  printf(($"+"3("=")"+"$));
  print((newline));
  printf(($2("ab")$));
  print((newline))
END

The first call repeats the string "-" ten times, so the format itself produces ten characters of output. The second brackets three equals signs between two plus signs, and the third repeats two letters twice. A replicator also works on a frame, but a frame inside the group consumes one value for each repetition.

$ a68g replicas.a68
----------
+===+
abab

whole, fixed, and float

A format is not the only way to control a field. The predeclared procedures whole, fixed, and float return a string that a program prints like any other value, which is often simpler inside a formula or a procedure.

values.a68
BEGIN
  print((whole(42, 0), "|", whole(42, 6), newline));
  print((fixed(3.14159, 0, 2), "|", fixed(3.14159, 8, 2), newline));
  print((float(1234.5678, 12, 2, 3), newline))
END

whole(n, 0) returns the digits alone, while whole(n, 6) pads the result to six characters and includes the sign. fixed(r, 0, 2) gives two decimals without a field, and fixed(r, 8, 2) pads it to eight characters. float produces exponent notation, and its last parameter is the width of the exponent.

$ a68g values.a68
42|   +42
3.14|   +3.14
+1234.57e +0

A format kept in a variable

Because a format denotation has mode FORMAT, it may be stored in a variable and passed to several calls. The declaration is made outside the clause when the format is shared, and the frames are filled at each call.

formatvar.a68
FORMAT row = $"| "g(-6,2)" | "g(-6,2)" |"$;

BEGIN
  printf((row, 1.5, 2.25));
  print((newline));
  printf((row, 10.0, -3.5));
  print((newline))
END

The name row stands for the whole format, including the bars and the spaces, so both lines have the same shape. Only the values differ, and the negative width of the frames keeps the numbers right justified. A procedure may also take a FORMAT parameter and pass it on to printf.

$ a68g formatvar.a68
|   1.50 |   2.25 |
|  10.00 |  -3.50 |

A table with a format

A format makes a table easy: one call reserves the width of a column, and the same width is used for every row. The header is literal text with the same spacing as the frames below it.

table.a68
BEGIN
  printf(($"    n       n*n"$));
  print((newline));
  FOR i TO 5 DO
    printf(($g(-5)$, i));
    printf(($g(-8)$, i * i));
    print((newline))
  OD
END

Each row writes the number in a field five characters wide and the square in a field eight characters wide. The header is written with spaces that place the words over the two columns, and because every number is right justified the digits line up. The loop needs no other output procedure than printf and print.

$ a68g table.a68
    n       n*n
    1       1
    2       4
    3       9
    4      16
    5      25

Lines and pages

The frame l ends the current line, and the frame p moves to the next page. Both may appear inside a format denotation, which makes a whole block of output part of one call.

lines.a68
BEGIN
  printf(($"line one"l$));
  printf(($"line two"l$));
  printf(($"line three"l$))
END

Each call writes its text and ends the line, so the three calls produce three lines. p writes a form feed character, which a terminal and a printer treat as the start of a new page; a program that writes to a mainframe printer uses it to control the pagination.

$ a68g lines.a68
line one
line two
line three

Next steps

The unformatted transput article covers print, write, and put without a format, and the reading input article shows the input side of the same procedures. The files article applies putf to a file of its own, and strings explains how a number becomes text with whole and fixed.

Source

Revised Report on the Algorithmic Language Algol 68

The Algol 68 Genie project

In this article we have written format denotations with literal text, frames, and replicators, set the width, decimals, and sign of numbers, printed strings of an exact width, seen the asterisks of a narrow field, used whole, fixed, and float, stored a format in a variable, built a table, and ended lines and pages from inside a format. The files article continues with the transput procedures on files of a program's own.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Algol 68 tutorials.