流复位精度

时间:2012-02-08 16:26:13

标签: c++ precision ofstream

我正在使用c ++来操作txt文件。 我需要写一些具有一定精度的数字,所以我在做:

    ofstrem file;
    file.open(filename, ios::app);
    file.precision(6);
    file.setf(ios::fixed, ios::floafield);
    //writing number on the file.....

现在我需要写其他东西,所以我需要重置精度。 我怎么能这样做?

3 个答案:

答案 0 :(得分:7)

首先使用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
}

Live demo.

答案 1 :(得分:4)

有两种可能的解决方案。如果你正在处理大块的 输出使用相同的格式参数,你可以使用一些东西 像这样:

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;

无需担心保存和恢复格式化状态。

答案 2 :(得分:1)

一个解决方案:

std::streamsize oldPres = file.precision(2);
file.setf(ios::fixed, ios::floafield);
… code continues …
file.precision(oldPres);
file.unsetf(std::ios::fixed);