Формат плавающей точки для 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 году.

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

Вы должны добавить

 #include  

Вам нужны streamовые манипуляторы

Вы можете «заполнить» пустые места любым желаемым символом. Как это:

 std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) << std::setfill( '0' ) << my_double; 
 std::cout << boost::format("%11.6f") % my_double; 

Вы должны #include

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

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

 std::cout << pressure << my_double; 

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

 class FFmt : public StateSavingManip { public: explicit FFmt( int width, int prec = 6, std::ios::fmtflags additionalFlags = static_cast(), 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 ); } 

это я, OP, Jive Dadson – пять лет спустя. C ++ 17 становится реальностью.

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

 #include  #include  #include  #include  namespace dj { template 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)...); 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)...); 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; } 

Для будущих посетителей, которые предпочитают использовать спецификации формата printf в стиле std :: ostream, вот еще один вариант, основанный на превосходной почте Мартина Йорка в другом вопросе SO: https://stackoverflow.com/a/535636 :

 #include  #include  #include  //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 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); } }; 

пример использования:

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

или даже:

 int val = 42; cout << val << " in hex is " << FMT(" 0x%x") << val << "\n"; 
  • Java: зачем вам нужно указывать 'f' в streamовом литерале?
  • Является ли плавающая точка == когда-либо ОК?
  • "F" после числа / float в Objective-C / C
  • Форматирование удваивается для вывода в C #
  • Преобразование double / float в строку
  • Почему 24.0000 не равно 24.0000 в MATLAB?
  • Как хранится плавающая запятая? Когда это имеет значение?
  • Деление с плавающей запятой против умножения с плавающей запятой
  • Что означают F и D в конце числовых литералов?
  • Как получить десятичную часть поплавка?
  • Манипулирование и сравнение плавающих точек в java
  • Давайте будем гением компьютера.