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.
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 '%)'
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; import std.format : formattedWrite; 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.891,011"
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. |
Exception 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.
Helper function that returns a FormatSpec for a single specifier given in fmt.
Char[] fmt
| A format specifier. |
FormatSpec with the specifier parsed. Exception 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(singleSpec(""));
assertThrown(singleSpec("2.3e"));
assertThrown(singleSpec("%2.3eTest"));
bools are formatted as "true" or "false" with %s and as "1" or "0" with integral-specific format specs.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
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".
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%s");
formatValue(w, null, spec);
writeln(w.data); // "null"
Integrals are formatted like printf does.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%d");
formatValue(w, 1337, spec);
writeln(w.data); // "1337"
Floating-point values are formatted like printf does.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%.1f");
formatValue(w, 1337.7, spec);
writeln(w.data); // "1337.7"
Individual characters (char, wchar, or dchar) are formatted as Unicode characters with %s and as integers with integral-specific format specs.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%c");
formatValue(w, 'a', spec);
writeln(w.data); // "a"
Strings are formatted like printf does.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%s");
formatValue(w, "hello", spec);
writeln(w.data); // "hello"
Static-size arrays are formatted as dynamic arrays.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
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"
Dynamic arrays are formatted as input ranges.
void[] is formatted like ubyte[].Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
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]"
Associative arrays are formatted by using ':' and ", " as separators, and enclosed by '[' and ']'.
Writer w
| The OutputRange to write to. |
T obj
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%s");
auto aa = ["H":"W"];
formatElement(w, aa, spec);
writeln(w.data); // "[\"H\":\"W\"]"
Aggregates (struct, union, class, and interface) are basically formatted by calling toString. toString should have one of the following signatures:
const void toString(scope void delegate(const(char)[]) sink, FormatSpec fmt); const void toString(scope void delegate(const(char)[]) sink, string fmt); const void toString(scope void delegate(const(char)[]) sink); const string toString();
toString has overridden Object.toString, it is used.toString, Type(field1, filed2, ...).formatValue allows to reuse existing format specifiers: import std.format;
struct Point
{
int x, y;
void toString(scope void delegate(const(char)[]) sink,
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)"
formatValue and formattedWrite. import std.array : appender;
import std.format;
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");
enum is formatted like its base value.
Writer w
| The OutputRange to write to. |
T val
| The value to write. |
FormatSpec!Char f
| The FormatSpec defining how to write the value. |
import std.array : appender;
auto w = appender!string();
auto spec = singleSpec("%s");
enum A { first, second, third }
formatElement(w, A.second, spec);
writeln(w.data); // "second"
Pointers are formatted as hex integers.
Delegates are formatted by '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;
return &foo;
}
writeln(to!string(&bar)); // "int delegate(short) @nogc delegate() pure nothrow @system"
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 Exception 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));
input ranges 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.
Char[] fmt
| Format string. For detailed specification, see formattedWrite. |
Args args
| Variadic list of arguments to format into returned string. |
fmt is known at compile-time: 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–2017 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_format.html