Floating point format for std::ostream

C++Floating PointCoutOstream

C++ Problem Overview


How do I do the following with std::cout?

double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"

I am just about ready to give up and use sprintf_s.

More generally, where can I find a reference on std::ostream formatting that lists everything in one place, rather than spreading it all out in a long tutorial?

EDIT Dec 21, 2017 - See my answer below. It uses features that were not available when I asked this question in 2012.

C++ Solutions


Solution 1 - C++

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;

Solution 2 - C++

std::cout << boost::format("%11.6f") % my_double;

You have to #include <boost\format.hpp>

Solution 3 - C++

In C++20 you'll be able to do

double my_double = 42.0;
char str[12];
std::format_to_n(str, sizeof(str), "{:11.6}", my_double); 

or

std::string s = std::format("{:11.6}", my_double); 

In the meantime you can use the {fmt} library that provides an implementation of format_to_n.

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Solution 4 - C++

In general, you want to avoid specifying things like 11 and 6 at the point of output. That's physical markup, and you want logical markup; e.g. pressure, or volume. That way, you define in a single place how pressure or volume are formatted, and if that formatting changes, you don't have to search through out the program to find where to change the format (and accidentally change the format of something else). In C++, you do this by defining a manipulator, which sets the various formatting options, and preferrably restores them at the end of the full expression. So you end up writing things like:

std::cout << pressure << my_double;

Although I definitly wouldn't use it in production code, I've found the following FFmt formatter useful for quicky jobs:

class FFmt : public StateSavingManip
{
public:
    explicit            FFmt(
                            int                 width,
                            int                 prec = 6,
                            std::ios::fmtflags  additionalFlags 
                                    = static_cast<std::ios::fmtflags>(),
                            char                fill = ' ' );

protected:
    virtual void        setState( std::ios& targetStream ) const;

private:
    int                 myWidth;
    int                 myPrec;
    std::ios::fmtflags  myFlags;
    char                myFill;
};

FFmt::FFmt(
    int                 width,
    int                 prec,
    std::ios::fmtflags  additionalFlags,
    char                fill )
    :   myWidth( width )
    ,   myPrec( prec )
    ,   myFlags( additionalFlags )
    ,   myFill( fill )
{
    myFlags &= ~ std::ios::floatfield
    myFlags |= std::ios::fixed
    if ( isdigit( static_cast< unsigned char >( fill ) )
             && (myFlags & std::ios::adjustfield) == 0 ) {
        myFlags |= std::ios::internal
    }
}

void
FFmt::setState( 
    std::ios&           targetStream ) const
{
    targetStream.flags( myFlags )
    targetStream.width( myWidth )
    targetStream.precision( myPrec )
    targetStream.fill( myFill )
}

This allows writing things like:

std::cout << FFmt( 11, 6 ) << my_double;

And for the record:

class StateSavingManip
{
public:
    StateSavingManip( 
            StateSavingManip const& other );
    virtual             ~StateSavingManip();
    void                operator()( std::ios& stream ) const;

protected:
    StateSavingManip();

private:
    virtual void        setState( std::ios& stream ) const = 0;

private:
    StateSavingManip&   operator=( StateSavingManip const& );

private:
    mutable std::ios*   myStream;
    mutable std::ios::fmtflags
                        mySavedFlags;
    mutable int         mySavedPrec;
    mutable char        mySavedFill;
};

inline std::ostream&
operator<<(
    std::ostream&       out,
    StateSavingManip const&
                        manip )
{
    manip( out );
    return out;
}

inline std::istream&
operator>>(
    std::istream&       in,
    StateSavingManip const&
                        manip )
{
    manip( in );
    return in;
}

StateSavingManip.cc:

namespace {

//      We maintain the value returned by ios::xalloc() + 1, and not
//      the value itself.  The actual value may be zero, and we need
//      to be able to distinguish it from the 0 resulting from 0
//      initialization.  The function getXAlloc() returns this value
//      -1, so we add one in the initialization.
int                 getXAlloc();
int                 ourXAlloc = getXAlloc() + 1;

int
getXAlloc()
{
    if ( ourXAlloc == 0 ) {
        ourXAlloc = std::ios::xalloc() + 1;
        assert( ourXAlloc != 0 );
    }
    return ourXAlloc - 1;
}
}

StateSavingManip::StateSavingManip()
    :   myStream( NULL )
{
}

StateSavingManip::StateSavingManip(
    StateSavingManip const&
                        other )
{
    assert( other.myStream == NULL );
}

StateSavingManip::~StateSavingManip()
{
    if ( myStream != NULL ) {
        myStream->flags( mySavedFlags );
        myStream->precision( mySavedPrec );
        myStream->fill( mySavedFill );
        myStream->pword( getXAlloc() ) = NULL;
    }
}

void
StateSavingManip::operator()( 
    std::ios&           stream ) const
{
    void*&              backptr = stream.pword( getXAlloc() );
    if ( backptr == NULL ) {
        backptr      = const_cast< StateSavingManip* >( this );
        myStream     = &stream;
        mySavedFlags = stream.flags();
        mySavedPrec  = stream.precision();
        mySavedFill  = stream.fill();
    }
    setState( stream );
}

Solution 5 - C++

#include <iostream>
#include <iomanip>

int main() {
    double my_double = 42.0;
    std::cout << std::fixed << std::setw(11)
        << std::setprecision(6) << my_double << std::endl;
    return 0;
}

Solution 6 - C++

For future visitors who prefer actual printf-style format specs with std::ostream, here is yet another variation, based on Martin York's excellent post in another SO question: https://stackoverflow.com/a/535636:

#include <iostream>
#include <iomanip>
#include <stdio.h> //snprintf

class FMT
{
public:
    explicit FMT(const char* fmt): m_fmt(fmt) {}
private:
    class fmter //actual worker class
    {
    public:
        explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {}
//output next object (any type) to stream:
        template<typename TYPE>
        std::ostream& operator<<(const TYPE& value)
        {
//            return m_strm << "FMT(" << m_fmt << "," << value << ")";
            char buf[40]; //enlarge as needed
            snprintf(buf, sizeof(buf), m_fmt, value);
            return m_strm << buf;
        }
    private:
        std::ostream& m_strm;
        const char* m_fmt;
    };
    const char* m_fmt; //save fmt string for inner class
//kludge: return derived stream to allow operator overloading:
    friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt)
    {
        return FMT::fmter(strm, fmt);
    }
};

usage example:

double my_double = 42.0;
cout << FMT("%11.6f") << my_double << "more stuff\n";

or even:

int val = 42;
cout << val << " in hex is " << FMT(" 0x%x") << val << "\n";

Solution 7 - C++

it's me, the OP, Jive Dadson - five years on. C++17 is becoming a reality.

The advent of variadic template parameters with perfect forwarding has made life so much simpler. The chained madness of ostream<< and boost::format% can be dispensed with. The function oprintf below fills the bill. Work in progress. Feel free to chime in on error-handling, etc...

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string_view>

namespace dj {

    template<class Out, class... Args>
    Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) {
	    const int sz = 512;
	    char buffer[sz];
	    int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...);

	    if (cx >= 0 && cx < sz) { 
		    return out.write(buffer, cx);
	    } else if (cx > 0) {
		    // Big output
		    std::string buff2;
		    buff2.resize(cx + 1);
		    snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...);
		    return out.write(buff2.data(), cx);
	    } else {
		    // Throw?
		    return out;
	    }
    }
}

int main() {
    const double my_double = 42.0;
    dj::oprintf(std::cout, "%s %11.6lf\n", "My double ", my_double);
    return 0;
}

Solution 8 - C++

Some great answers already; kudos to those!

This is based on some of them. I have added type assertions for POD types, since they are the only safe types usable with printf().

#include <iostream>
#include <stdio.h>
#include <type_traits>

namespace fmt {
namespace detail {

template<typename T>
struct printf_impl
{
    const char* fmt;
    const T v;

    printf_impl(const char* fmt, const T& v) : fmt(fmt), v(v) {}
};

template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, std::ostream& >::type
operator<<(std::ostream& os, const printf_impl<T>& p)
{
    char buf[40];
    ::snprintf(buf, sizeof(buf), p.fmt, p.v, 40);
    return os << buf;
}

} // namespace detail

template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, detail::printf_impl<T> >::type
printf(const char* fmt, const T& v)
{
    return detail::printf_impl<T>(fmt, v);
}

} // namespace fmt

Example usage it as below.

std::cout << fmt::printf("%11.6f", my_double);

Give it a try on Coliru.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJive DadsonView Question on Stackoverflow
Solution 1 - C++Kiril KirovView Answer on Stackoverflow
Solution 2 - C++AndreyView Answer on Stackoverflow
Solution 3 - C++vitautView Answer on Stackoverflow
Solution 4 - C++James KanzeView Answer on Stackoverflow
Solution 5 - C++Pete BeckerView Answer on Stackoverflow
Solution 6 - C++djulienView Answer on Stackoverflow
Solution 7 - C++Jive DadsonView Answer on Stackoverflow
Solution 8 - C++ϹοδεMεδιϲView Answer on Stackoverflow