Formatted Output

April 8, 2014

The only output functions provided by standard Scheme are display, for plain output, and write, for system-formatted output. That’s rather limiting. At the other extreme, Lisp provides the format function, which has more options than you can dream about (before I discarded it in favor of the HyperSpec, the spine of my printed copy of CLtL2 was broken in two places, format and loop). Many languages provide some kind of formatted output — does anyone remember PIC in COBOL? In today’s exercise we will implement the printf function popularized by C and used in several languages.

There are three functions in the printf family: (sprintf fmt expr) returns a string formatted according to the specification given by format and containing the values expr …; (printf fmt expr) displays a string formatted similarly to sprintf to the current output port, and (fprintf port fmt expr) displays a string formatted similarly to sprintf to the indicated port. The fmt and port arguments are always required.

The fmt argument is a string that contains literal text, escape sequences, and specifications of how the expressions should be formatted. A specification consists of a literal percent-sign %, zero or more modifiers, and a single-character specifier. The single-character specifiers that we will support are:

c ascii character
d decimal integer
f floating-point number
o octal integer
s string
x hexadecimal integer
% literal percent sign

There should be as many expressions as there are format specifiers in the fmt string, except that a % literal percent sign specifier does not consume an expression. As many as four modifiers may appear between the literal percent sign % that starts a specifier and the single-character specifier that ends it:

- left-justify the expression in its field; if not given, the expression is right-justified
0 left-pad with leading zeros instead of spaces
width pad field to this width using spaces (or zeros)
.prec digits to right of decimal point, or maximum string length

The modifiers must appear in the order shown above. The width and prec arguments are unsigned decimal integers.

Escape sequences are introduced by a backslash; the following escape sequences are supported:

\b backspace
\f formfeed
\n newline
\r carriage return
\t horizontal tab
\ddd character with octal value ddd, where ddd is 1 to 3 digits between 0 and 7 inclusive
\c any other character c literally, for instance \\ for backslash or \" for quotation mark

Depending on the environment, a newline may (or may not) imply a carriage return, or vice-versa. Several examples are given on the next page.

Your task is to write a function that provides formatted output for your language, using the definition of printf given above or some other specification that is suitable for your language and your aspirations. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.


Pages: 1 2