#lang scribble/manual @(require scribble/manual ;scribble/class scribble/eval (for-label racket/base )) @(define the-eval (make-base-eval)) @title{sprintf functions} @author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] @defmodule[sprintf] This module provides a compact @tt{printf}-style string formatting facility for Racket. It is inspired by C-style format strings, but implemented on top of @racket[racket/format]. The core functionality is provided by @racket[sprintf] and @racket[sprintf*]. @section{Overview} The module exports two formatting functions: @itemlist[ @item{@racket[sprintf] — formats using variadic arguments} @item{@racket[sprintf*] — formats using an explicit argument list} ] Both functions use the same format-string syntax and semantics. @section{Exports} @defproc[(sprintf [format string?] [arg any/c] ...) string?]{ Formats the string @racket[format] by substituting the given arguments according to printf-style conversion specifications. Arguments are consumed sequentially from left to right. An error is raised if there are too many or too few arguments for the format string. } @defproc[(sprintf* [format string?] [args list?]) string?]{ Variant of @racket[sprintf] where the arguments are supplied explicitly as a list. This form is useful when arguments are constructed dynamically or passed through higher-order functions. } @section{Format String Syntax} A format specification has the general form: @verbatim{ %[flags][width][.precision][length]type } Only a well-defined subset of the traditional @tt{printf} syntax is supported. @section{Supported Conversion Types} The following conversion specifiers are recognized: @itemlist[ @item{@tt{%d} — decimal integer} @item{@tt{%x} — hexadecimal integer} @item{@tt{%f} — floating-point number} @item{@tt{%s} — string} @item{@tt{%%} — literal percent sign} ] @section{Flags} The following flags are supported: @itemlist[ @item{@tt{0} — pad numeric output with zeros instead of spaces} @item{@tt{-} — left-align the result within the field width} ] If no flag is specified, numeric values are right-aligned and padded with spaces. @section{Field Width} A minimum field width may be specified as a decimal number: @verbatim{ %8d %-10s } If the formatted value is shorter than the field width, it is padded according to the alignment rules. @section{Dynamic Width and Precision} Both width and precision may be specified using @tt{*}. In that case, the value is taken from the argument list. Example: @verbatim{ (sprintf "%*.*f" 8 3 1.23456) } In this example: @itemlist[ @item{the first argument specifies the field width} @item{the second argument specifies the precision} @item{the third argument is the value to be formatted} ] The arguments supplying width or precision must be numbers; otherwise an error is raised. @section{Precision} Precision has different meanings depending on the conversion type: @itemlist[ @item{for numeric conversions, it controls the number of digits after the decimal point} @item{for strings, it specifies the maximum output width} ] If no precision is specified: @itemlist[ @item{numeric values default to precision 0 for integers} @item{strings are not truncated} ] @section{Length Modifiers} The length modifier field (e.g. @tt{l}) is parsed for syntactic compatibility but otherwise ignored. It has no semantic effect. @section{Type Checking and Errors} The formatter performs runtime type checking: @itemlist[ @item{numeric conversion specifiers require numeric arguments} @item{@tt{%s} requires a string argument} ] Errors are raised in the following situations: @itemlist[ @item{arguments remain but no format specifiers are left} @item{format specifiers remain but no arguments are left} @item{@tt{*} is used but no corresponding numeric argument is available} @item{argument types do not match the conversion specifier} ] Error messages are designed to be explicit and descriptive. @section{Implementation Notes} Internally, the formatter uses regular-expression driven parsing and delegates the actual formatting to @racket[~r] and @racket[~a] from @racket[racket/format]. The implementation is intentionally strict: mismatches between format strings and arguments are treated as programming errors and reported immediately.