Search code examples
c++fmtc++23

Difference between C++ stream and print() - fillers


It has been a while since I posted any questions on StackOverflow; I hope I remember more or less the appropriate way to address a question (sorry in advance).

I was playing with C++ streams and the FMT library, which provides a preview to C++23 print. Streams are chill when setting fillers to complete the display width of an integer. Example:

const int y = 730;
cout << "y = " << setw(5) << y << endl;
cout << "y = " << setfill('0') << setw(5) << y << endl;
cout << "y = " << setfill('X') << setw(5) << y << endl;
cout << "y = " << setfill('*') << setw(5) << y << endl;

The output is

y =   730
y = 00730
y = XX730
y = **730

I was trying to set the same fillers (including 'X' and '*' chars) using fmt::print—something like:

print("y = {:5d}\n", y);
print("y = {:05d}\n", y);

Well, I failed to include 'X' and '*'. I am not claiming it is a good idea to have random chars as fillers; I am just curious as I need to explain the difference between these commands to students.

Thanks in advance. Vivian


Solution

  • The manual shows following grammar for integer format specifiers:

    format_spec ::=  [[fill]align][sign]["#"]["0"][width]["." precision]["L"][type]
    fill        ::=  <a character other than '{' or '}'>
    align       ::=  "<" | ">" | "^"
    

    Here format_spec is the part inside of {: }.

    So specifying a custom filler (fill) also requires specifying alignment (you want >, i.e. align to the right):

    fmt::print("y = {:X>5d}\n", y); // XX730
    fmt::print("y = {:*>5d}\n", y); // **730