7

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

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

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

4

3 回答 3

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
}

现场演示。

于 2012-02-08T16:28:31.367 回答
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;

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

于 2012-02-08T16:46:54.463 回答
1

一种解决方案:

std::streamsize oldPres = file.precision(2);
file.setf(ios::fixed, ios::floafield);
… code continues …
file.precision(oldPres);
file.unsetf(std::ios::fixed);
于 2012-09-21T05:02:09.807 回答