Wing wrote:
Thanks for those who answered my question previously.
Everytime I want to output high precision numbers, I use the following
code:
cout << setprecision (9) << f << endl;
where f is some double number.
However, I don't want to add "setprecisi on (9)" in every "cout" and
"iofstream" in order to output/input high precision number, because I
need to modify my codes substantially in this case.
What can I do such that my program can output high precision numbers
without modifying the codes substantially?
Thanks.
You could define your own version of cout in the following way:
#include <iostream>
#include <ostream>
#include <iomanip>
class CCustomOutputSt ream
{
public:
CCustomOutputSt ream (std::ostream& p_refUnderlying OStream, int
p_iDefaultPreci sion)
: m_pInternalOStr eam (&p_refUnderlyi ngOStream),
m_iDefaultPreci sion (p_iDefaultPrec ision),
m_NextPrecision (-1)
{
if (p_iDefaultPrec ision < 0 || p_iDefaultPreci sion 20)
throw exception ();
}
CCustomOutputSt ream& operator<< (std::ostream& (__cdecl
*_F)(std::ostre am&))
{
// Invoke the passed I/O function for the internal stream.
_F (*m_pInternalOS tream);
return *this;
}
CCustomOutputSt ream& operator<< (std::ios& (__cdecl *_F)(std::ios&) )
{
// Invoke the passed I/O function for the internal stream.
_F (*m_pInternalOS tream);
return *this;
}
/*! \brief This method can be used to access the internal stream.
*/
std::ostream* GetInternalStre am ()
{
return m_pInternalOStr eam;
}
protected:
/*! \brief The internal output stream.
*/
std::ostream* m_pInternalOStr eam;
/*! \brief If the user has provided a precision, we will use this
* value for the next floating point value.
* If this value is -1, we should use the default precision for the
* next floating point value.
*/
int m_NextPrecision ;
/*! \brief The default precision that should be used for floating
* point values.
*/
int m_iDefaultPreci sion;
public:
/*! \brief This is how outputting data is done in general: Just
* forward the call to the internal stream.
*/
template <class T>
CCustomOutputSt ream& operator<< (T p_RHS)
{
// Forward the call to the internal output stream.
*m_pInternalOSt ream << p_RHS;
return *this;
}
/*! \brief Template specialization for the setprecision manipulator.
*/
template<>
CCustomOutputSt ream& operator<< (std::_Smanip<s td::streamsize>
p_Manipulator)
{
// If the manipulator function is sbfun (the function that sets
// the precision of a given stream),
// we remember the argument, so that the next print of a floating
// point variable is done with this
// precision (Had we not remembered this, we would print the next
// floating point value with our internal
// default precision.
if (p_Manipulator. _Pf == std::setprecisi on (0)._Pf)
{
m_NextPrecision = p_Manipulator._ Manarg;
}
return *this;
}
/*! \brief Template specialization for floating point values.
*/
template<>
CCustomOutputSt ream& operator<< (float p_RHS)
{
// If the precision was explicitely set by a previous call
// to setprecision, we use this precision. Else
// we use the standard precision of this custom stream.
if (m_NextPrecisio n 0)
{
m_pInternalOStr eam->precision (m_NextPrecisio n);
m_NextPrecision = -1;
}
else
m_pInternalOStr eam->precision (m_iDefaultPrec ision);
// Print the float value with the set precision.
*m_pInternalOSt ream << p_RHS;
return *this;
}
template<>
CCustomOutputSt ream& operator<< (double p_RHS)
{
// If the precision was explicitely set by a previous call to
// setprecision, we use this precision. Else
// we use the standard precision of this custom stream.
if (m_NextPrecisio n 0)
{
m_pInternalOStr eam->precision (m_NextPrecisio n);
m_NextPrecision = -1;
}
else
m_pInternalOStr eam->precision (m_iDefaultPrec ision);
// Print the float value with the set precision.
*m_pInternalOSt ream << p_RHS;
return *this;
}
};
CCustomOutputSt ream Mycout (std::cout, 7);
int main ()
{
Mycout << "Pi with default precision: "
<< 3.1415926535897 << std::endl
<< "Pi with precision 2: "
<< std::setprecisi on (2) << 3.1415926535897 << std::endl
<< "Pi with default precision: "
<< 3.1415926535897 << std::endl;
return 0;
}
All you have to do is replacing of cout by Mycout (which can be done
with replace-in-files tools). If you use output streams to files, you
have to create one custom output stream for each such stream. If you use
the internals of a stream (like failbit), you may need to add these
features to CCustomOutputSt ream, so that you don't have to retrieve the
internal stream every time. CCustomOutputSt ream is also not a template
that can work with UNICODE strings (I didn't want to spend to much time
on this example).
Regards,
Stuart