Подтвердить что ты не робот

Формат плавающей точки для std:: ostream

Как мне сделать следующее: std:: cout?

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

Я просто готов отказаться и использовать sprintf_s.

В более общем плане, где я могу найти ссылку на форматирование std:: ostream, которая перечисляет все в одном месте, а не распространяет все это в длинном учебнике?

EDIT 21 декабря 2017 г. - См. мой ответ ниже. Он использует функции, которые недоступны, когда я задавал этот вопрос в 2012 году.

4b9b3361

Ответ 1

std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) << my_double;

Вам нужно добавить

#include <iomanip>

Вам нужны манипуляторы потока

Вы можете "заполнить" пустые места любым желаемым char. Вот так:

std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) 
          << std::setfill( '0' ) << my_double;

Ответ 2

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

Вы должны #include <boost\format.hpp>

Ответ 3

#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;
}

Ответ 4

В общем, вы не хотите указывать такие вещи, как 11 и 6 на точка вывода. Эта физическая разметка, и вам нужна логическая разметка; например pressure или volume. Таким образом, вы определяете в одном месте как форматируются давление или объем, и если это форматирование изменяется, вам не нужно искать программу, чтобы найти, где можно изменить формат (и случайно изменить формат чего-то другого). В С++, вы делаете это, определяя манипулятор, который устанавливает различные варианты форматирования и предпочтительно восстанавливать их в конце полного выражение. Поэтому вы в конечном итоге пишете такие вещи, как:

std::cout << pressure << my_double;

Хотя я определенно не использовал его в производственном коде, я нашел следующий FFmt formatter полезен для быстрых заданий:

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 )
}

Это позволяет записывать такие вещи, как:

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

И для записи:

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 );
}

Ответ 5

это я, ОП, Джив Дадсон - пять лет спустя. С++ 17 становится реальностью.

Появление параметров вариационного шаблона с совершенной пересылкой сделало жизнь намного проще. Прикованное безумие ostream < и boost:: format% можно отказаться. Функция oprintf ниже заполняет счет. Работа в процессе. Не стесняйтесь отвечать на обработку ошибок и т.д.

#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;
}