Reputation: 1358
I'm using c++ to manipulate txt files. I need to write some numbers with a certain precision so I'm doing:
ofstrem file;
file.open(filename, ios::app);
file.precision(6);
file.setf(ios::fixed, ios::floafield);
//writing number on the file.....
now I need to write other stuff, so I need to reset precision. how can I do it?
Upvotes: 8
Views: 13504
Reputation: 153899
There are two possible solutions. If you're handling a large block of output which uses the same formatting parameters, you can use something like this:
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 );
}
};
Just define an instance of it at the top of the block doing the output.
Most of the time, however, I'll be defining my own manipulator, which derives from something like:
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 ;
}
The implementation is a bit tricky, since you have to take into account that if several manipulators are used in the same expression, the compiler can construct them (and thus destruct them) in any order it pleases. So:
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 ) ;
}
The derived manipulator then does whatever it has to in its implementation of setState
. Given this, you can write things like:
std::cout << FFmt( 6, 2 ) << someValue << std::endl;
without having to worry about saving and restoring the formatting state.
Upvotes: 4
Reputation: 2557
One solution:
std::streamsize oldPres = file.precision(2);
file.setf(ios::fixed, ios::floafield);
… code continues …
file.precision(oldPres);
file.unsetf(std::ios::fixed);
Upvotes: 1
Reputation: 385098
Retrieve the stream's original precision value first with precision()
, store it, change it, do your insertions, then change it back to the stored value.
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
}
Upvotes: 9