【问题标题】:Class that resets all of the changes made with iomanip: setprecision, setfill and the flags in one call重置使用 iomanip 所做的所有更改的类:一次调用中的 setprecision、setfill 和标志
【发布时间】:2016-07-12 08:11:50
【问题描述】:

所以我知道有很多次我想重置我使用 iomanip 所做的格式更改。我创建了一个类,您可以使用它来获取 ostream 对象的格式,例如用于写入/读取文件的 std::cout 或 fstream 对象也可以。我这样做主要是为了练习并帮助有同样问题的其他人。

您所要做的就是使用ResetIOmanip 类创建一个对象。如果您在没有参数的情况下创建它,它将使用 std::cout 作为默认值。您可以将 ostream/istream 对象作为参数放入,它将适用于文件。确保在进行任何格式更改之前调用它。然后当它完成时,从对象调用成员函数resetAll(),它将重置标志、重置精度和重置填充字符。

请随时向 cmets 提供如何改进我的头文件。我还在学习,一直在寻找建设性的批评。谢谢。

【问题讨论】:

    标签: c++ iomanip


    【解决方案1】:

    这是头文件:

    ResetIOmanip.h

    /*
    File:   ResetIOmanip.h
    Author: kingcobra1986
    Date:   7/11/2016
    Class:  ResetIOmanip
    Purpose: 
            When the instance of the class ResetIOmanip is created, the 
            current settings will be saved and can be recalled by calling
            the member function resetAll().
    */
    
    #ifndef _RESETIOMANIP
    #define _RESETIOMANIP
    #include <iostream>
    #include <iomanip>
    
    class ResetIOmanip {
    private:
        std::ostream * _ostream;
        std::istream * _istream;
        std::streamsize _precision;
        std::ios_base::fmtflags _flags;
        char _fill;
    
        //Set the original precision
        void set_precision () {
            if (this->_ostream != nullptr)
                this->_precision = this->_ostream->precision ();
            if (this->_istream != nullptr)
                this->_precision = this->_istream->precision ();
        }
    
        //Set the original flags
        void set_flags () { 
            if (this->_ostream != nullptr)
                this->_flags = this->_ostream->flags ();
            if (this->_istream != nullptr)
                this->_flags = this->_istream->flags ();
        }
    
        //Set the original fill
        void set_fill () { 
            if (this->_ostream != nullptr)
                this->_fill = this->_ostream->fill ();
            if (this->_istream != nullptr)
                this->_fill = this->_istream->fill ();
        }
    
    public:
        //Default Constructor
        ResetIOmanip ( std::ostream & stream = std::cout ) {
            this->_ostream = &stream;
            this->_istream = nullptr;
            this->set_precision ();
            this->set_flags ();
            this->set_fill ();
            stream << "Fill: " << this->get_fill () << std::endl;
        }
    
        //Overloaded Constructor
        ResetIOmanip ( std::istream & stream ) {
            this->_ostream = nullptr;
            this->_istream = &stream;
            this->set_precision ();
            this->set_flags ();
            this->set_fill ();
        }
    
        //Get the original precision
        std::streamsize get_precision () { return this->_precision; }
    
        //Get the original flags
        std::ios_base::fmtflags get_flags () { return this->_flags; }
    
        //Get the original fill
        char get_fill () { return this->_fill; }
    
        //Reset to the original precision
        void reset_precision () {
            if (this->_ostream != nullptr)
                this->_ostream->precision ( this->_precision );
            if (this->_istream != nullptr)
                this->_istream->precision ( this->_precision );
        }
    
        //Reset to the original flags
        void reset_flags () {
            if (this->_ostream != nullptr)
                this->_ostream->flags ( this->_flags );
            if (this->_istream != nullptr)
                this->_istream->flags ( this->_flags );
        }
    
        //Reset to the original fill
        void reset_fill () { 
            if (this->_ostream != nullptr) {
                this->_ostream->fill ( this->_fill );
            }
            if (this->_istream != nullptr)
                this->_istream->fill ( this->_fill );
        }
    
        //Reset to all of the original settings
        void resetAll () {
            this->reset_precision ();
            this->reset_flags ();
            this->reset_fill ();
        }
    };
    
    #endif
    

    这是我的测试方法:

    Main.cpp

    //This is to test ResetIOmanip objects
    #include <iostream>
    #include <fstream>
    #include "ResetIOmanip.h"
    
    int main () {
        using std::cout;
        using std::endl;
    
        double randNumb1 = 45.235723;
        double randNumb2 = 1.49;
    
        ResetIOmanip resetFormats1;
        cout << "Original 1: " << randNumb1 << endl;
        cout << "Original 2: " << randNumb2 << endl;
        cout << "setprecision(4) for #1: " << std::setprecision ( 4 ) << randNumb1 << endl;
        cout << "setprecision(4) for #2: " << std::setprecision ( 4 ) << randNumb2 << endl << endl;
    
        cout << "setprecision(4) and fixed for #1: " << std::fixed << std::setprecision ( 4 ) << randNumb1 << endl;
        cout << "setprecision(4) and fixed for #2: " << std::fixed << std::setprecision ( 4 ) << randNumb2 << endl;
    
        cout << "setfill(x) and setw(10) for #1: " << std::setfill ( 'x' ) << std::setw ( 10 ) << randNumb1 << endl;
        cout << "setfill(x) and setw(10) for #2: " << std::setfill ( 'x' ) << std::setw ( 10 ) << randNumb2 << endl << endl;
    
        cout << "Testing Format #1: " << randNumb1 << endl;
        cout << "Testing Format #2: " << randNumb2 << endl;
    
        cout << "Testing Format with set width(10) #1: " << std::setw(10) << randNumb1 << endl;
        cout << "Testing Format with set width(10) #2: " << std::setw ( 10 ) << randNumb2 << endl << endl;
    
        cout << "RESETING - TESTING CLASS" << endl;
    
        resetFormats1.resetAll ();
        cout << "Testing Format #1: " << randNumb1 << endl;
        cout << "Testing Format #2: " << randNumb2 << endl;
    
        cout << "Testing Format with set width(10) #1: " << std::setw ( 10 ) << randNumb1 << endl;
        cout << "Testing Format with set width(10) #2: " << std::setw ( 10 ) << randNumb2 << endl << endl;
    
    
    
        cout << "Testing with ostream to testResetIOmanip.txt" << endl;
        std::ofstream testingOut;
        testingOut.open ( "testResetIOmanip.txt", std::ios::out );
        if (testingOut.fail ()) {
            cout << "ERROR: Cannot open the file" << endl;
            return 0;
        }
        ResetIOmanip resetFormats2 ( testingOut );
    
        testingOut << "Original 1: " << randNumb1 << endl;
        testingOut << "Original 2: " << randNumb2 << endl;
        testingOut << "setprecision(4) for #1: " << std::setprecision ( 4 ) << randNumb1 << endl;
        testingOut << "setprecision(4) for #2: " << std::setprecision ( 4 ) << randNumb2 << endl << endl;
    
        testingOut << "setprecision(4) and fixed for #1: " << std::fixed << std::setprecision ( 4 ) << randNumb1 << endl;
        testingOut << "setprecision(4) and fixed for #2: " << std::fixed << std::setprecision ( 4 ) << randNumb2 << endl;
    
        testingOut << "setfill(x) and setw(10) for #1: " << std::setfill ( 'x' ) << std::setw ( 10 ) << randNumb1 << endl;
        testingOut << "setfill(x) and setw(10) for #2: " << std::setfill ( 'x' ) << std::setw ( 10 ) << randNumb2 << endl << endl;
    
        testingOut << "Testing Format #1: " << randNumb1 << endl;
        testingOut << "Testing Format #2: " << randNumb2 << endl;
    
        testingOut << "Testing Format with set width(10) #1: " << std::setw ( 10 ) << randNumb1 << endl;
        testingOut << "Testing Format with set width(10) #2: " << std::setw ( 10 ) << randNumb2 << endl << endl;
    
        testingOut << "RESETING - TESTING CLASS" << endl;
        resetFormats2.resetAll ();
    
        testingOut << "Testing Format #1: " << randNumb1 << endl;
        testingOut << "Testing Format #2: " << randNumb2 << endl;
    
        testingOut << "Testing Format with set width(10) #1: " << std::setw ( 10 ) << randNumb1 << endl;
        testingOut << "Testing Format with set width(10) #2: " << std::setw ( 10 ) << randNumb2 << endl << endl;
    
        testingOut.close ();
    
        return 0;
    }
    

    【讨论】:

    • 我发现这样的东西很有用。这是我最近使用的一个变体:github.com/HowardHinnant/date/blob/master/date.h#L850-L875 它不保存 precision 只是因为我不需要它。这可以很容易地添加(我可能应该)。您可以使用std::ios* 而不是单独的ostream*istream*(它们都派生自ios,这是存储格式的地方)。我在析构函数中恢复。这样,即使在特殊情况下,它也总是可以完成。因此,我使我的重置器不可复制。
    猜你喜欢
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    相关资源
    最近更新 更多