This module implements the formatting functionality for strings and I/O. It's comparable to C99's vsprintf()
and uses a similar format encoding scheme.
For an introductory look at std.format's capabilities and how to use this module see the dedicated DWiki article.
This module centers around two functions:
Function Name | Description |
---|---|
formattedRead | Reads values according to the format string from an InputRange. |
formattedWrite | Formats its arguments according to the format string and puts them to an OutputRange. |
formattedWrite
for a description of the format string. Function Name | Description |
---|---|
format | Returns a GC-allocated string with the formatting result. |
sformat | Puts the formatting result into a preallocated array. |
std.string
to be easily available. formatValue
and unformatValue
are used for the plumbing. Signals a mismatch between a format and its corresponding argument.
import std.exception : assertThrown; assertThrown!FormatException(format("%d", "foo"));
Interprets variadic argument list args
, formats them according to fmt
, and sends the resulting characters to w
. The encoding of the output is the same as Char
. The type Writer
must satisfy std.range.primitives.isOutputRange!(Writer, Char)
.
The variadic arguments are normally consumed in order. POSIX-style positional parameter syntax is also supported. Each argument is formatted into a sequence of chars according to the format specification, and the characters are passed to w
. As many arguments as specified in the format string are consumed and formatted. If there are fewer arguments than format specifiers, a FormatException
is thrown. If there are more remaining arguments than needed by the format specification, they are ignored but only if at least one argument was formatted.
The format string supports the formatting of array and nested array elements via the grouping format specifiers %( and %). Each matching pair of %( and %) corresponds with a single array argument. The enclosed sub-format string is applied to individual array elements. The trailing portion of the sub-format string following the conversion specifier for the array element is interpreted as the array delimiter, and is therefore omitted following the last array element. The %| specifier may be used to explicitly indicate the start of the delimiter, so that the preceding portion of the string will be included following the last array element. (See below for explicit examples.)
Writer w
| Output is sent to this writer. Typical output writers include std.array.Appender!string and std.stdio.LockingTextWriter . |
Char[] fmt
| Format string. |
A args
| Variadic argument list. |
FormatException
being thrown. FormatString: FormatStringItem* FormatStringItem: '%%' '%' Position Flags Width Separator Precision FormatChar '%(' FormatString '%)' '%-(' FormatString '%)' OtherCharacterExceptPercent Position: empty Integer '$' Flags: empty '-' Flags '+' Flags '#' Flags '0' Flags ' ' Flags Width: empty Integer '*' Separator: empty ',' ',' '?' ',' '*' '?' ',' Integer '?' ',' '*' ',' Integer Precision: empty '.' '.' Integer '.*' Integer: Digit Digit Integer Digit: '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' FormatChar: 's'|'c'|'b'|'d'|'o'|'x'|'X'|'e'|'E'|'f'|'F'|'g'|'G'|'a'|'A'|'|'
Flag | Types affected | Semantics |
---|---|---|
'-' | numeric | Left justify the result in the field. It overrides any 0 flag. |
'+' | numeric | Prefix positive numbers in a signed conversion with a +. It overrides any space flag. |
'#' | integral ('o') | Add to precision as necessary so that the first digit of the octal formatting is a '0', even if both the argument and the Precision are zero. |
'#' | integral ('x', 'X') | If non-zero, prefix result with 0x (0X). |
'#' | floating | Always insert the decimal point and print trailing zeros. |
'0' | numeric | Use leading zeros to pad rather than spaces (except for the floating point values nan and infinity ). Ignore if there's a Precision. |
' ' | numeric | Prefix positive numbers in a signed conversion with a space. |
"true"
or "false"
.import std.stdio; void main() { writefln("My items are %(%s %).", [1,2,3]); writefln("My items are %(%s, %).", [1,2,3]); }The output is:
My items are 1 2 3. My items are 1, 2, 3.The trailing end of the sub-format string following the specifier for each item is interpreted as the array delimiter, and is therefore omitted following the last array item. The %| delimiter specifier may be used to indicate where the delimiter begins, so that the portion of the format string prior to it will be retained in the last array element:
import std.stdio; void main() { writefln("My items are %(-%s-%|, %).", [1,2,3]); }which gives the output:
My items are -1-, -2-, -3-.These compound format specifiers may be nested in the case of a nested array argument:
import std.stdio; void main() { auto mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; writefln("%(%(%d %)\n%)", mat); writeln(); writefln("[%(%(%d %)\n %)]", mat); writeln(); writefln("[%([%(%d %)]%|\n %)]", mat); writeln(); }The output is:
1 2 3 4 5 6 7 8 9 [1 2 3 4 5 6 7 8 9] [[1 2 3] [4 5 6] [7 8 9]]Inside a compound format specifier, strings and characters are escaped automatically. To avoid this behavior, add '-' flag to
"%("
. import std.stdio; void main() { writefln("My friends are %s.", ["John", "Nancy"]); writefln("My friends are %(%s, %).", ["John", "Nancy"]); writefln("My friends are %-(%s, %).", ["John", "Nancy"]); }which gives the output:
My friends are ["John", "Nancy"]. My friends are "John", "Nancy". My friends are John, Nancy.
format
for details): import std.array : appender; auto writer = appender!string(); writer.formattedWrite!"%s is the ultimate %s."(42, "answer"); writeln(writer.data); // "42 is the ultimate answer." // Clear the writer writer = appender!string(); formattedWrite(writer, "Date: %2$s %1$s", "October", 5); writeln(writer.data); // "Date: 5 October"
writeln(format("%,d", 1000)); // "1,000" writeln(format("%,f", 1234567.891011)); // "1,234,567.891011" writeln(format("%,?d", '?', 1000)); // "1?000" writeln(format("%,1d", 1000)); // "1,0,0,0" writeln(format("%,*d", 4, -12345)); // "-1,2345" writeln(format("%,*?d", 4, '_', -12345)); // "-1_2345" writeln(format("%,6?d", '_', -12345678)); // "-12_345678" assert(format("%12,3.3f", 1234.5678) == " 1,234.568", "'" ~ format("%12,3.3f", 1234.5678) ~ "'");
Reads characters from input range r
, converts them according to fmt
, and writes them to args
.
R r
| The range to read from. |
const(Char)[] fmt
| The format of the data to read. |
S args
| The drain of the data read. |
FormatException
if S.length == 0
and fmt
has format specifiers.format
for details): string s = "hello!124:34.5"; string a; int b; double c; s.formattedRead!"%s!%s:%s"(a, b, c); assert(a == "hello" && b == 124 && c == 34.5);
A General handler for printf
style format specifiers. Used for building more specific formatting functions.
import std.array; auto a = appender!(string)(); auto fmt = "Number: %2.4e\nString: %s"; auto f = FormatSpec!char(fmt); f.writeUpToNextSpec(a); writeln(a.data); // "Number: " writeln(f.trailing); // "\nString: %s" writeln(f.spec); // 'e' writeln(f.width); // 2 writeln(f.precision); // 4 f.writeUpToNextSpec(a); writeln(a.data); // "Number: \nString: " writeln(f.trailing); // "" writeln(f.spec); // 's'
Minimum width, default 0
.
Precision. Its semantics depends on the argument type. For floating point numbers, precision dictates the number of decimals printed.
Number of digits printed between separators.
Set to DYNAMIC
when the separator character is supplied at runtime.
Character to insert between digits.
Special value for width and precision. DYNAMIC
width or precision means that they were specified with '*'
in the format string and are passed at runtime through the varargs.
Special value for precision, meaning the format specifier contained no explicit precision.
The actual format specifier, 's'
by default.
Index of the argument for positional parameters, from 1
to ubyte.max
. (0
means not used).
Index of the last argument for positional parameter range, from 1
to ubyte.max
. (0
means not used).
The format specifier contained a '-'
(printf
compatibility).
The format specifier contained a '0'
(printf
compatibility).
The format specifier contained a ' '
(printf
compatibility).
The format specifier contained a '+'
(printf
compatibility).
The format specifier contained a '#'
(printf
compatibility).
The format specifier contained a ','
In case of a compound format specifier starting with "%("
and ending with "%)"
, _nested
contains the string contained within the two separators.
In case of a compound format specifier, _sep
contains the string positioning after "%|"
. sep is null
means no separator else sep.empty
means 0 length separator.
_trailing
contains the rest of the format string.
Construct a new FormatSpec
using the format string fmt
, no processing is done until needed.
Gives a string containing all of the member variables on their own line.
OutputRange writer
| A char accepting output range
|
string
when not using an output range; void
otherwise.Helper function that returns a FormatSpec
for a single specifier given in fmt
.
Char[] fmt
| A format specifier. |
FormatSpec
with the specifier parsed. FormatException
when more than one specifier is given or the specifier is malformed.import std.exception : assertThrown; auto spec = singleSpec("%2.3e"); writeln(spec.trailing); // "" writeln(spec.spec); // 'e' writeln(spec.width); // 2 writeln(spec.precision); // 3 assertThrown!FormatException(singleSpec("")); assertThrown!FormatException(singleSpec("2.3e")); assertThrown!FormatException(singleSpec("%2.3eTest"));
Formats any value into Char
accepting OutputRange
, using the given FormatSpec
.
struct
, union
, class
, and interface
are formatted by calling toString
. toString
should have one of the following signatures: void toString(W)(ref W w, scope const ref FormatSpec fmt) void toString(W)(ref W w) string toString();Where
W
is an output range which accepts characters. The template type does not have to be called W
. The following overloads are also accepted for legacy reasons or for use in virtual functions. It's recommended that any new code forgo these overloads if possible for speed and attribute acceptance reasons. void toString(scope void delegate(const(char)[]) sink, const ref FormatSpec fmt); void toString(scope void delegate(const(char)[]) sink, string fmt); void toString(scope void delegate(const(char)[]) sink);For the class objects which have input range interface,
toString
has overridden Object.toString
, it is used.struct
and union
objects which does not have toString
, Type(field1, filed2, ...)
.Writer w
| The output range to write to. |
T val
| The value to write. |
FormatSpec!Char f
| The std.format.FormatSpec defining how to write the value. |
formatValue
and formattedWrite
. import std.array : appender; auto writer1 = appender!string(); writer1.formattedWrite("%08b", 42); auto writer2 = appender!string(); auto f = singleSpec("%08b"); writer2.formatValue(42, f); assert(writer1.data == writer2.data && writer1.data == "00101010");
bool
s are formatted as "true"
or "false"
with %s
and as 1
or 0
with integral-specific format specs. import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); formatValue(w, true, spec); writeln(w.data); // "true"
null
literal is formatted as "null"
. import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); formatValue(w, null, spec); writeln(w.data); // "null"
core.stdc.stdio.printf
. import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%d"); formatValue(w, 1337, spec); writeln(w.data); // "1337"
core.stdc.stdio.printf
import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%.1f"); formatValue(w, 1337.7, spec); writeln(w.data); // "1337.7"
char,
wchar, or
dchar`) are formatted as Unicode characters with %s
and as integers with integral-specific format specs. import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%c"); formatValue(w, 'a', spec); writeln(w.data); // "a"
core.stdc.stdio.printf
import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); formatValue(w, "hello", spec); writeln(w.data); // "hello"
import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); char[2] two = ['a', 'b']; formatValue(w, two, spec); writeln(w.data); // "ab"
void[]
is formatted like ubyte[]
.import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); auto two = [1, 2]; formatValue(w, two, spec); writeln(w.data); // "[1, 2]"
':'
and ", "
as separators, and enclosed by '['
and ']'
. import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); auto aa = ["H":"W"]; formatValue(w, aa, spec); writeln(w.data); // "[\"H\":\"W\"]"
enum
s are formatted like their base value import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); enum A { first, second, third } formatValue(w, A.second, spec); writeln(w.data); // "second"
toString
, which takes an output range. It's recommended that any toString
using output ranges use std.range.primitives.put
rather than use the put
method of the range directly. import std.array : appender; import std.range.primitives; static struct Point { int x, y; void toString(W)(ref W writer, scope const ref FormatSpec!char f) if (isOutputRange!(W, char)) { // std.range.primitives.put put(writer, "("); formatValue(writer, x, f); put(writer, ","); formatValue(writer, y, f); put(writer, ")"); } } auto w = appender!string(); auto spec = singleSpec("%s"); auto p = Point(16, 11); formatValue(w, p, spec); writeln(w.data); // "(16,11)"
struct
with a defined toString
, this time using the scope delegate
method. This method is now discouraged for non-virtual functions. If possible, please use the output range method instead. static struct Point { int x, y; void toString(scope void delegate(scope const(char)[]) @safe sink, scope const FormatSpec!char fmt) const { sink("("); sink.formatValue(x, fmt); sink(","); sink.formatValue(y, fmt); sink(")"); } } auto p = Point(16,11); writeln(format("%03d", p)); // "(016,011)" writeln(format("%02x", p)); // "(10,0b)"
import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); auto q = cast(void*) 0xFFEECCAA; formatValue(w, q, spec); writeln(w.data); // "FFEECCAA"
import core.simd; import std.array : appender; auto w = appender!string(); auto spec = singleSpec("%s"); static if (is(float4)) { version (X86) {} else { float4 f4; f4.array[0] = 1; f4.array[1] = 2; f4.array[2] = 3; f4.array[3] = 4; formatValue(w, f4, spec); writeln(w.data); // "[1, 2, 3, 4]" } }
ReturnType delegate(Parameters) FunctionAttributes
import std.conv : to; int i; int foo(short k) @nogc { return i + k; } @system int delegate(short) @nogc bar() nothrow pure { int* p = new int(1); i = *p; return &foo; } writeln(to!string(&bar)); // "int delegate(short) @nogc delegate() pure nothrow @system" writeln( () @trusted { return bar()(3); }()); // 4
Reads a value from the given input range according to spec and returns it as type T
.
T | the type to return |
Range input
| the input range to read from |
FormatSpec!Char spec
| the FormatSpec to use when reading from input
|
input
of type T
FormatException
if spec
cannot read a type T
std.conv.parse
and std.conv.to
auto str = "false"; auto spec = singleSpec("%s"); writeln(unformatValue!bool(str, spec)); // false str = "1"; spec = singleSpec("%d"); assert(unformatValue!bool(str, spec));
auto str = "null"; auto spec = singleSpec("%s"); writeln(str.unformatValue!(typeof(null))(spec)); // null
auto str = "123"; auto spec = singleSpec("%s"); writeln(str.unformatValue!int(spec)); // 123 str = "ABC"; spec = singleSpec("%X"); writeln(str.unformatValue!int(spec)); // 2748 str = "11610"; spec = singleSpec("%o"); writeln(str.unformatValue!int(spec)); // 5000
import std.math : approxEqual; auto str = "123.456"; auto spec = singleSpec("%s"); assert(str.unformatValue!double(spec).approxEqual(123.456));
auto str = "aaa"; auto spec = singleSpec("%s"); writeln(str.unformatValue!char(spec)); // 'a' // Using a numerical format spec reads a Unicode value from a string str = "65"; spec = singleSpec("%d"); writeln(str.unformatValue!char(spec)); // 'A' str = "41"; spec = singleSpec("%x"); writeln(str.unformatValue!char(spec)); // 'A' str = "10003"; spec = singleSpec("%d"); writeln(str.unformatValue!dchar(spec)); // '✓'
string str = "aaa"; auto spec = singleSpec("%s"); writeln(str.unformatValue!(dchar[])(spec)); // "aaa"d str = "aaa"; spec = singleSpec("%s"); dchar[3] ret = ['a', 'a', 'a']; writeln(str.unformatValue!(dchar[3])(spec)); // ret str = "[1, 2, 3, 4]"; spec = singleSpec("%s"); writeln(str.unformatValue!(int[])(spec)); // [1, 2, 3, 4] str = "[1, 2, 3, 4]"; spec = singleSpec("%s"); int[4] ret2 = [1, 2, 3, 4]; writeln(str.unformatValue!(int[4])(spec)); // ret2
auto str = `["one": 1, "two": 2]`; auto spec = singleSpec("%s"); writeln(str.unformatValue!(int[string])(spec)); // ["one":1, "two":2]
Format arguments into a string.
If the format string is fixed, passing it as a template parameter checks the type correctness of the parameters at compile-time. This also can result in better performance.
Char[] fmt
| Format string. For detailed specification, see formattedWrite . |
Args args
| Variadic list of arguments to format into returned string. |
auto s = format!"%s is %s"("Pi", 3.14); writeln(s); // "Pi is 3.14" static assert(!__traits(compiles, {s = format!"%l"();})); // missing arg static assert(!__traits(compiles, {s = format!""(404);})); // surplus arg static assert(!__traits(compiles, {s = format!"%d"(4.03);})); // incompatible arg
Format arguments into buffer buf which must be large enough to hold the result.
buf
containing the formatted string. RangeError
if buf
isn't large enough to hold the formatted string. A FormatException
if the length of args
is different than the number of format specifiers in fmt
.format
for details): char[10] buf; writeln(buf[].sformat!"foo%s"('C')); // "fooC" writeln(sformat(buf[], "%s foo", "bar")); // "bar foo"
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_format.html