我正在使用C++来操作文本文件。 我需要以一定的精度写入一些数字,所以我这样做:
ofstrem file;
file.open(filename, ios::app);
file.precision(6);
file.setf(ios::fixed, ios::floafield);
//writing number on the file.....
现在我需要写其他内容,所以我需要重新设置精度。我该如何做?
首先使用 precision()
方法检索流的原始精度值,将其存储,更改它,进行插入操作,然后将其更改回存储的值。
int main() {
std::stringstream ss;
ss << 1.12345 << " ";
std::streamsize p = ss.precision();
ss.precision(2);
ss << 1.12345 << " ";
ss.precision(p);
ss << 1.12345;
cout << ss.str(); // 1.12345 1.1 1.12345
}
file.precision()
应该返回一个 int
,稍后可以将其传递给 file.precision( newValue )
。另一方面,您对精度所做的任何操作都不会影响标志;您需要对它们执行相同的操作。并确保在发生异常时恢复两者。 - James Kanzestd::streamsize
。它可能是一个整数,但写成 std::streamsize
,因为这就是它的类型。 - Lightness Races in Orbit有两种可能的解决方案。如果您处理的是一个大块输出,它使用相同的格式参数,您可以使用类似以下的内容:
class IOSave
{
std::ios& myStream;
std::ios::fmtflags myFlags;
std::streamsize myPrecision;
char myFill;
public:
IOSave( std::ios& userStream )
: myStream( userStream )
, myFlags( userStream.flags() )
, myPrecision( userStream.precision() )
, myFill( userStream.fill() )
{
}
~IOSave()
{
myStream.flags( myFlags );
myStream.precision( myPrecision );
myStream.fill( myFill );
}
};
在输出代码块的顶部定义一个实例即可。
然而,大多数情况下,我会定义自己的操作器,其派生自以下内容:
class StateSavingManipulator
{
mutable std::ios* myStream;
mutable std::ios::fmtflags mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
virtual void setState( std::ios& stream ) const = 0 ;
protected:
StateSavingManipulator();
public:
virtual ~StateSavingManipulator();
void operator()( std::ios& stream ) const ;
};
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 ;
}
实现起来有点棘手,因为您必须考虑到如果在同一个表达式中使用了多个操作器,编译器可以按照任意顺序构造它们(因此也会按照任意顺序销毁它们)。所以:
namespace {
int getXAlloc() ;
int ourXAlloc = getXAlloc() + 1 ;
int getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1 ;
assert( ourXAlloc != 0 ) ;
}
return ourXAlloc - 1 ;
}
}
StateSavingManipulator::StateSavingManipulator()
: myStream( NULL )
{
}
StateSavingManipulator::~StateSavingManipulator()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags ) ;
myStream->precision( mySavedPrec ) ;
myStream->fill( mySavedFill ) ;
myStream->pword( getXAlloc() ) = NULL ;
}
}
void StateSavingManipulator::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 ) ;
}
setState
时执行必须进行的任何操作。有了这个,你可以写出像这样的东西:std::cout << FFmt( 6, 2 ) << someValue << std::endl;
无需担心保存和恢复格式状态。
std::streamsize oldPres = file.precision(2);
file.setf(ios::fixed, ios::floafield);
… code continues …
file.precision(oldPres);
file.unsetf(std::ios::fixed);
ios_base::precision
有两个重载,其中一个就是你要找的。 - Lightness Races in Orbit