How to use C++ std::ostream with printf-like formatting?
The only thing you can do with std::ostream
directly is the well known <<
-syntax:
int i = 0;
std::cout << "this is a number: " << i;
And there are various IO manipulators that can be used to influence the formatting, number of digits, etc. of integers, floating point numbers etc.
However, that is not the same as the formatted strings of printf
. C++11 does not include any facility that allows you to use string formatting in the same way as it is used with printf
(except printf
itself, which you can of course use in C++ if you want).
In terms of libraries that provide printf
-style functionality, there is boost::format
, which enables code such as this (copied from the synopsis):
std::cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50;
Also note that there is a proposal for inclusion of printf
-style formatting in a future version of the Standard. If this gets accepted, syntax such as the below may become available:
std::cout << std::putf("this is a number: %d\n",i);
How do I use string format like printf while saving to a file?
If you write your file in C style (using FILE*
), you can use fprintf()
.
For C++-style ostream
output, such formatting is done with stream manipulators:
out << "var1: " << std::fixed << std::setprecision(2) << var1 << " var2: " << var2;
Sometimes this is inconvenient (such as when the format is language-dependent, and you need to retrieve it from the translation file).
ostream implementatuon using printf
I assume you mean something that overloads operator<<
by "an ostream
-like class". It's easy to identify the type of the argument to a function just by having overloads. For example, you might have:
ostreamlike& ostreamlike::operator<<(int x)
{
printf("%d", x);
return *this;
}
ostreamlike& ostreamlike::operator<<(float x)
{
printf("%f", x);
return *this;
}
The format of the output is determined by whichever overload is picked.
Floating point format for std::ostream
std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double;
You need to add
#include <iomanip>
You need stream manipulators
You may "fill" the empty places with whatever char you want. Like this:
std::cout << std::fixed << std::setw(11) << std::setprecision(6)
<< std::setfill('0') << my_double;
Can I use an std::ostream to print into a given buffer?
(Thank @BoP and @T.C. for the two parts of this solution)
This can be done... if you're willing to use a deprecated C++ construct: std:ostrstream
.
#include <strstream>
#include <iostream>
int main() {
const size_t n = 20;
char my_buffer[n];
std::ostrstream my_os(my_buffer, n);
my_os << "hello" << ',' << 123 << '\0';
std::cout << my_buffer << '\n';
}
Notes about this code:
- It works (GodBolt)
- It is valid C++98! ... of course I had to let go of
std::span
,auto
type inference etc. It's also valid C++11 and later standards. - This will construct an
std::strstreambuf
, which is what anstd::ostrstream
uses directly, from your buffer of chars.
(see this on GodBolt)
Unfortunately, with the deprecation of std::ostrstream
, we were left with no fully-valid alternative up to, and including, C++20. You would need to implement a custom std::basic_streambuf
, and assign it to an std::ostream
. :-(
But in C++23 - you are luck! The standard library does offer exactly what you asked for: std::spanstream
: A std::ostream
backed by a span of char
's which it is given at construction.
make std::ostream automatically ident when encountering special characters
boost::iostreams makes this fairly easy, you can define filters then chain them together with an output stream to transform the input to the desired output:
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
namespace io = boost::iostreams;
struct QuoteOutputFilter {
typedef char char_type;
typedef io::output_filter_tag category;
int indent = 0;
template<typename Sink>
bool newLine(Sink& snk)
{
std::string str = "\n" + std::string(indent * 4, ' ');
return io::write(snk, str.c_str(), str.size());
}
template<typename Sink>
bool put(Sink& snk, char c)
{
switch (c)
{
case '<':
io::put(snk, c);
indent += 1;
return newLine(snk);
case ',':
io::put(snk, c);
return newLine(snk);
case '>':
indent -= 1;
newLine(snk);
return io::put(snk, c);
default:
return io::put(snk, c);
}
}
};
int main()
{
io::filtering_ostream out;
out.push(QuoteOutputFilter());
out.push(std::cout);
out << "test0<test1<test2, test3<test4> > >";
}
C++ equivalent of printf() or formatted output
This is what you want:
std::cout << std::fixed << std::setprecision(2);
std::cout << dNum;
and don't forget to :
#include <iostream>
#include <iomanip>
how to let ss f work like printf(%g, f);
%g
is documented as follows:
converts floating-point number to decimal or decimal exponent notation depending on the value and the precision.
For the g conversion style conversion with style e or f will be performed.
For the G conversion style conversion with style E or F will be performed.
Let P equal the precision if nonzero,
6
if the precision is not specified, or1
if the precision is 0
. Then, if a conversion with style E would have an exponent of X:
if P > X ≥ −4, the conversion is with style f or F and precision P − 1 − X.
otherwise, the conversion is with style e or E and precision P − 1.
Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left. For infinity and not-a-number conversion style see notes.
The stream equivalent would look something like this:
#include <cmath>
float f = ...;
int X; // the exponent
int P = 6; // the desired precision
X = std::floor(std::log10(f));
std::stringstream ss;
if ((P > X) && (X >= −4))
ss << std::fixed << std::setprecision(P - 1 − X);
else
ss << std::scientific << std::setprecision(P - 1);
ss << f;
c++: sprintf directly to ostream
I'm not aware of any way to do it, but you surely don't need it.
ostream
was specifically designed to avoid printf-like formatting, so I believe any printf/sprintf format output can be redesigned to operate directly on an ostream
. Just use the << overloaded operator to do your formatting.
Related Topics
Why Is (Void) 0 a No Operation in C and C++
Std::Max - Expected an Identifier
What's an Expression and Expression Statement in C++
Deterministic Builds Under Windows
C++ Standard Practice: Virtual Interface Classes VS. Templates
Default Values in Templates with Template Arguments ( C++ )
Variable Length Arrays (Vla) in C and C++
C++ Move Semantics and Exceptions
Add a Method to Existing C++ Class in Other File
How to Find the Name of the Calling Function
What Use Are Const Pointers (As Opposed to Pointers to Const Objects)
Window C/C++ Crypto API Examples and Tips
How to Call Function After Window Is Shown
Is There a C++11 Syntax File for Vim
How to Pass a C++ Lambda to a C-Callback That Expects a Function Pointer and a Context