String Formatting in D Programming Language

import std.stdio;
import std.format;

struct Point {
    int x, y;
}

void main() {
    // D offers excellent support for string formatting similar to printf tradition.
    // Here are some examples of common string formatting tasks.

    // D offers several formatting specifiers designed to format general D values.
    // For example, this prints an instance of our Point struct.
    auto p = Point(1, 2);
    writefln("struct1: %s", p);

    // If the value is a struct, the %s specifier will include the struct's field names.
    writefln("struct2: %s", p);

    // There's no direct equivalent to Go's %#v in D, but we can achieve similar results
    // by defining a custom toString method for the struct if needed.

    // To print the type of a value, use %s with typeid.
    writefln("type: %s", typeid(p));

    // Formatting booleans is straightforward.
    writefln("bool: %s", true);

    // There are many options for formatting integers.
    // Use %d for standard, base-10 formatting.
    writefln("int: %d", 123);

    // This prints a binary representation.
    writefln("bin: %b", 14);

    // This prints the character corresponding to the given integer.
    writefln("char: %c", 33);

    // %x provides hex encoding.
    writefln("hex: %x", 456);

    // There are also several formatting options for floats.
    // For basic decimal formatting use %f.
    writefln("float1: %f", 78.9);

    // %e and %E format the float in (slightly different versions of) scientific notation.
    writefln("float2: %e", 123400000.0);
    writefln("float3: %E", 123400000.0);

    // For basic string printing use %s.
    writefln("str1: %s", `"string"`);

    // To double-quote strings, use %s with quotes.
    writefln(`str2: "%s"`, `"string"`);

    // As with integers seen earlier, %x renders the string in base-16,
    // with two output characters per byte of input.
    writefln("str3: %x", "hex this");

    // To print a representation of a pointer, use %x.
    writefln("pointer: %x", &p);

    // When formatting numbers you will often want to control the width and precision
    // of the resulting figure. To specify the width of an integer, use a number
    // after the % in the format specifier. By default the result will be right-justified
    // and padded with spaces.
    writefln("width1: |%6d|%6d|", 12, 345);

    // You can also specify the width of printed floats, though usually you'll also
    // want to restrict the decimal precision at the same time with the width.precision syntax.
    writefln("width2: |%6.2f|%6.2f|", 1.2, 3.45);

    // To left-justify, use the - flag.
    writefln("width3: |%-6.2f|%-6.2f|", 1.2, 3.45);

    // You may also want to control width when formatting strings,
    // especially to ensure that they align in table-like output.
    // For basic right-justified width:
    writefln("width4: |%6s|%6s|", "foo", "b");

    // To left-justify use the - flag as with numbers.
    writefln("width5: |%-6s|%-6s|", "foo", "b");

    // So far we've seen writef and writefln, which print the formatted string to stdout.
    // format returns a string without printing it anywhere.
    string s = format("format: a %s", "string");
    writeln(s);

    // You can format+print to other output streams using write and writeln.
    stderr.writeln(format("io: an %s", "error"));
}

To run this program, save it as string_formatting.d and use the D compiler:

$ dmd string_formatting.d
$ ./string_formatting

The output will be similar to the Go version, with slight differences due to D’s specific formatting rules and output.

D’s standard library (Phobos) provides powerful string formatting capabilities through the std.format module, which is similar to Go’s fmt package. The main differences are in the syntax of format specifiers and some language-specific features, but the overall concept remains the same.