How to Use C++ Std::Ostream with Printf-Like Formatting

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:

  1. It works (GodBolt)
  2. 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.
  3. This will construct an std::strstreambuf, which is what an std::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, or 1 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



Leave a reply



Submit