Std :: coutで次のことを行うにはどうすればよいですか?
double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"
Sprintf_sをあきらめて使用する準備ができました。
より一般的には、すべてを1つの場所にリストするstd :: ostreamフォーマットのリファレンスを、長いチュートリアルで広めるのではなく、どこで見つけることができますか?
EDIT 2017年12月21日-以下の私の答えをご覧ください。 2012年にこの質問をしたときに利用できなかった機能を使用しています。
std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) << my_double;
追加する必要があります
#include <iomanip>
ストリームマニピュレーター が必要です
空の場所に任意の文字を「埋める」ことができます。このような:
std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 )
<< std::setfill( '0' ) << my_double;
std::cout << boost::format("%11.6f") % my_double;
必ず #include <boost\format.hpp>
#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;
}
一般に、出力の時点で11
や6
などを指定しないようにします。それは物理的なマークアップであり、論理的なマークアップが必要です。例えばpressure
、またはvolume
。そうすれば、圧力またはボリュームのフォーマット方法を1か所で定義でき、そのフォーマットが変更されても、フォーマットを変更する場所を見つけるためにプログラム全体を検索する必要はありません(誤って他のフォーマットを変更します) 。 C++では、マニピュレータを定義することでこれを行います。マニピュレータは、さまざまなフォーマットオプションを設定し、完全な式の最後にオプションを復元することを推奨します。したがって、次のようなことを書くことになります。
std::cout << pressure << my_double;
私は間違いなく本番コードでは使用しませんが、次のFFmt
フォーマッターがquickyジョブに役立つことを発見しました。
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 );
}
それは私、OP、ジャイブ・ダドソンです-5年後。 C++ 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;
}
Std :: ostreamで実際のprintfスタイルのフォーマット仕様を好む将来の訪問者向けに、別のSO質問: 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);
}
};
使用例:
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";