C++ streams and Formatting manipulators

C++ provides a way to format the stream data such as intending the data of output stream, setting the base as hexadecimal or octal, etc. C++ provides this functionality through ios and ios_base classes.

The ios_base and ios classes provides the formatting functionality by implementing some format states information and bit masks. The ios_base class contains the members which can be used to change the precision, width, and formatting control flags of the stream.

    class ios_base
    {
        public:
           ...
           typedef _Ios_Fmtflags fmtflags;
        ...
        protected:
           ...
           streamsize      _M_precision;
           streamsize      _M_width;
           fmtflags        _M_flags;
       ...
    };

The ios class contains the fill attribute which can be used with width attribute to add some characters before or after the output.

    template<typename _CharT, typename _Traits>
    class basic_ios : public ios_base
    {
        ...
        protected:
            ...
            mutable char_type     _M_fill;
    }

Setting precision

ios_base class provides precision function to set the precision of floating point output. There are two variants of this function:

    • streamsize precision(streamsize __prec) receives the new precision value to be set and returns the old precison value.
      • inline streamsize
      • precision(streamsize __prec)
      • {
      • streamsize __old = _M_precision;
      • _M_precision = __prec;
      • return __old;
      • }
      • The following example changes the precision value of floating point value
      • #include <iostream>
      • using namespace std;
      • int main()
      • {
      • float numerator = 1, denominator = 3;
      • cout<<(numerator/denominator)<<"\n";
      • cout.precision(4);
      • cout<<(numerator/denominator)<<"\n";
      • return 0;
      • }
      • $ g++ format.cc -o format
      • $ ./format
      • 0.333333
      • 0.3333
    • streamsize precision const() returns the exsiting value of precision.
      • inline streamsize
      • precision(streamsize __prec)
      • {
      • streamsize __old = _M_precision;
      • _M_precision = __prec;
      • return __old;
      • }

Setting width and fill characters

The ios_base class provides the width function which can be used to specify the minimum number of characters to be used for the next output operation of an integer.

    inline streamsize width(streamsize __wide)
    {
        streamsize __old = _M_width;
        _M_width = __wide;
        return __old;
    }

Consider the following example

    #include <iostream>
    using namespace std;
    int main()
    {
        int distance = 10;
        cout<<"The distance is ";
        cout.width(5);
        cout<<distance;
        cout<<" metres\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    The distance is    10 metres

In the above function we set the width for the output operation to 5. The value of distance variable took only two characters, so three spcaes were printed to make sure the value of distance variable was printed with 5 characters.

In the above example we spaces were used as padding characters to make sure the output of the distance variable took 5 characters. We can change the padding character usng the fill function provided in ios class.

    #include<iostream>
    using namespace std;
    int main()
    {
        int distance = 10;
        cout<<"The distance is ";
        cout.width(5);
        cout.fill('#');
        cout<<distance;
        cout<<" metres\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    The distance is ###10 metres

There are couple of points to keep in mind while using width function.

    • width function only affects the next output operation only. The subsequent output operations wouldn't use the specified width value.
    • If the value of the integer is greater than the value specified in width function, even then complete value of the integer would be printed.
      • #include <iostream>
      • using namespace std;
      • int main()
      • {
      • int distance = 100;
      • cout<<"The distance is ";
      • cout.width(2);
      • cout<<distance;
      • cout<<" metres\n";
      • return 0;
      • }
      • $ g++ format.cc -o format
      • $ ./format
      • The distance is 100 metres

Both ios and ios_base class provide variants of functions fill and width which do not accpet any argument and return the exsiting values of fill character and width respectively.

    • char_type fill() returns the corrent value of fill character
      • template<typename _CharT, typename _Traits>
      • class basic_ios : public ios_base
      • {
      • ...
      • public:
      • char_type
      • fill() const
      • {
      • if (!_M_fill_init)
      • {
      • _M_fill = this->widen(' ');
      • _M_fill_init = true;
      • }
      • return _M_fill;
      • }
      • }
    • streamsize width() returns the current value of width
      • class ios_base
      • {
      • ...
      • public:
      • inline streamsize width() const
      • { return _M_width; }
      • }

Manipulating formatting flags

The fmtflags is interpreted as a bit mask whose various bits represent particluar features of formatting state.

    enum _Ios_Fmtflags
    {
        _S_boolalpha  = 1L << 0,
        _S_dec        = 1L << 1,
        _S_fixed      = 1L << 2,
        _S_hex        = 1L << 3,
        _S_internal   = 1L << 4,
        _S_left       = 1L << 5,
        _S_oct        = 1L << 6,
        _S_right      = 1L << 7,
        _S_scientific = 1L << 8,
        _S_showbase   = 1L << 9,
        _S_showpoint  = 1L << 10,
        _S_showpos    = 1L << 11,
        _S_skipws     = 1L << 12,
        _S_unitbuf    = 1L << 13,
        _S_uppercase  = 1L << 14,
        _S_adjustfield    = _S_left | _S_right | _S_internal,
        _S_basefield  = _S_dec | _S_oct | _S_hex,
        _S_floatfield     = _S_scientific | _S_fixed,
        _S_ios_fmtflags_end = 1L << 16
    };

The ios_base class also defines some conatsnats that can be used to address the bits of the fmtflags bitmask.

    class ios_base
    {
        ...
        /// Insert/extract @c bool in alphabetic rather than numeric format.
        static const fmtflags boolalpha =   _S_boolalpha;
        /// Converts integer input or generates integer output in decimal base.
        static const fmtflags dec =         _S_dec;
        /// Generate floating-point output in fixed-point notation.
        static const fmtflags fixed =       _S_fixed;
        /// Converts integer input or generates integer output in hexadecimal base.
        static const fmtflags hex =         _S_hex;
        /// Adds fill characters at a designated internal point in certain
        /// generated output, or identical to @c right if no such point is
        /// designated.
        static const fmtflags internal =    _S_internal;
        /// Adds fill characters on the right (final positions) of certain
        /// generated output.  (I.e., the thing you print is flush left.)
        static const fmtflags left =        _S_left;
        /// Converts integer input or generates integer output in octal base.
        static const fmtflags oct =         _S_oct;
        /// Adds fill characters on the left (initial positions) of certain
        /// generated output.  (I.e., the thing you print is flush right.)
        static const fmtflags right =       _S_right;
        /// Generates floating-point output in scientific notation.
        static const fmtflags scientific =  _S_scientific;
        /// Generates a prefix indicating the numeric base of generated integer
        /// output.
        static const fmtflags showbase =    _S_showbase;
        /// Generates a decimal-point character unconditionally in generated
        /// floating-point output.
        static const fmtflags showpoint =   _S_showpoint;
        /// Generates a + sign in non-negative generated numeric output.
        static const fmtflags showpos =     _S_showpos;
        /// Skips leading white space before certain input operations.
        static const fmtflags skipws =      _S_skipws;
        /// Flushes output after each output operation.
        static const fmtflags unitbuf =     _S_unitbuf;
        /// Replaces certain lowercase letters with their uppercase equivalents
        /// in generated output.
        static const fmtflags uppercase =   _S_uppercase;
        /// A mask of left|right|internal.  Useful for the 2-arg form of @c setf.
        static const fmtflags adjustfield = _S_adjustfield;
        /// A mask of dec|oct|hex.  Useful for the 2-arg form of @c setf.
        static const fmtflags basefield =   _S_basefield;
        /// A mask of scientific|fixed.  Useful for the 2-arg form of @c setf.
        static const fmtflags floatfield =  _S_floatfield;
        
        ...
    };

The istream and ostream classes inherit from ios_base and thus provide the functionality the formatting functionality for standard input (cin), standard ouput (cout), and standard error streams (cerr.)

We can use the format flag to display the boolean variables as true or false instead of their numerical values.

    #include <iostream>
    using namespace std;
    int main()
    {
        bool flag = true;
        cout<<flag<<"\n";
        cout.setf(ios::boolalpha);
        cout<<flag<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    1
    true

The ios_base class provides couple of functions to manipulate the formatting flags.

    • setf and flags function to set the bits in the format flags
    • unsetf function to clear the bits in the format flags
    • flags function to retrieve the current format flags

setf function

The setf function can be used to set the formatting flags maintained in ios_base class. There are two variants of setf functions defined:

    • setf(fmtflags __fmtfl) : This function sets the bits specified in __fmtfl argument to the exisiting format flags. The bits on the exisiting format flags remain set and returns the older value o formatting control flags.
    • e.g. if the exisiting format field was set to a value 0x0040 and value 0x0001 was passed as the argument then the new value of format flags would be 0x4001.
      • /**
      • * @brief Setting new format flags.
      • * @param fmtfl Additional flags to set.
      • * @return The previous format control flags.
      • *
      • * This function sets additional flags in format control. Flags that
      • * were previously set remain set.
      • */
      • inline fmtflags
      • setf(fmtflags __fmtfl)
      • {
      • fmtflags __old = _M_flags;
      • _M_flags |= __fmtfl;
      • return __old;
      • }
      • The following example sets the ios::showpos flag to display the + sign for positive numbers.
      • #include <iostream>
      • using namespace std;
      • int main()
      • {
      • int value = 10;
      • cout<<value<<"\n";
      • cout.setf(ios_base::showpos);
      • cout<<value<<"\n";
      • return 0;
      • }
      • $ g++ format.cc -o format
      • $ ./format
      • 10
      • +10
    • setf(fmtflags __fmtfl, fmtflags __mask) : This funtion clears the bits specified in __mask argument from the exisiting format flag, and then set the bits speciified in the __fmtfl argument to the exsiitng format flags and returns the older value o formatting control flags.
    • e.g. if the existing format flag had value 0x4001 and the setf was called with 0x0002 as __fmtfl and 0x0001 as __mask, then the new value of the format flag would be set to 0x0042.
      • /**
      • * @brief Setting new format flags.
      • * @param fmtfl Additional flags to set.
      • * @param mask The flags mask for @a fmtfl.
      • * @return The previous format control flags.
      • *
      • * This function clears @a mask in the format flags, then sets
      • * @a fmtfl @c & @a mask. An example mask is @c ios_base::adjustfield.
      • */
      • inline fmtflags
      • setf(fmtflags __fmtfl, fmtflags __mask)
      • {
      • fmtflags __old = _M_flags;
      • _M_flags &= ~__mask;
      • _M_flags |= (__fmtfl & __mask);
      • return __old;
      • }
      • The reason for providing this second variant is that some of the formatting features take more than one bits and only one of the bits should be enabled at once e.g. in order to set the justification of the output one of the three bits can be set (for left, right, or internal justifications.) If the justification is already set to something, then we need to clear the three bits first and then set the bit representing the new justification. For this purpose we can call the second variant which will clear the all the bits related to justification and then set the new justification bit. In order to do that the ios_base class defines some flags which represent the all the bits for specific features:
      • ios_base::basefield
      • ios_base::floatfield
      • ios_base::adjustfield
      • The following example sets the base of the number to hexadecimal.
      • #include <iostream>
      • using namespace std;
      • int main()
      • {
      • int value = 10;
      • cout<<value<<"\n";
      • cout.setf(ios_base::hex, ios_base::basefield);
      • cout<<value<<"\n";
      • return 0;
      • }
      • $ g++ format.cc -o format
      • $ ./format
      • 10
      • a

unsetf function

unsetf function clears the bits specified as arguments.

    inline void unsetf(fmtflags __mask) { _M_flags &= ~__mask; }

The following example sets the output format of floating point values to scientific and then unsets the formatting flag to set the default value.

    #include <iostream>
    using namespace std;
    int main()
    {
        float value = 0.01f;
        cout<<value<<"\n";
        cout.setf(ios_base::scientific, ios_base::floatfield);
        cout<<value<<"\n";
        cout.unsetf(ios_base::scientific);
        cout<<value<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    0.01
    1.000000e-02
    0.01

flags function

There are two variants of flags functions defined.

    • fmtflags flags(fmtflags __fmtfl) overwrites the exisiting formatting flags to the value specified as argument and returns the old formatting flags.
      • inline fmtflags flags(fmtflags __fmtfl)
      • {
      • fmtflags __old = _M_flags;
      • _M_flags = __fmtfl;
      • return __old;
      • }
      • The following example sets the base for numbers to hexadecimal and sets the display of hexadecimal numbers to uppercase.
      • #include <iostream>
      • using namespace std;
      • int main()
      • {
      • int value = 10;
      • cout<<value<<"\n";
      • cout.flags(ios_base::hex | ios_base::uppercase);
      • cout<<value<<"\n";
      • return 0;
      • }
      • $ g++ format.cc -o format
      • $ ./format
      • 10
      • A
    • fmtflags flags() function returns the current value of formatting control flags.
      • inline fmtflags flags() const { return _M_flags; }

Manipulators

C++ provides an elegant way to specify the formatting flags. ios_base class defines some functions that call the the setf and unsetf functions with the appropriate flags. e.g. the boolalpha function can be called, which will internally call the setf function with the ios_base::boolaplha argument.

    #include <iostream>
    using namespace std;
    int main()
    {
        bool status = true;
        cout<<status<<"\n";
        boolalpha(cout);
        cout<<status<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    1
    true

However, things can be simplified further. The manipulators can be used with the insertion and extraction operators as well. e.g.

    #include <iostream>
    using namespace std;
    int main()
    {
        bool status = true;
        cout<<boolalpha<<status<<"\n";
        return 0;
    }

Following manipulators are defined in ios_base class which call setf and unsetf functions internally.

Then there are some manipulators which do not call the setf or unsetf flags but manipulate the stream directly.

Manipulators with arguments

C++ also defines the manipulators which accept arguments as well.

Manipulator

setprecision
width

Argument

Precision value

Width value

As with other manipulators, these can be used alonf with insertion and extraction operators as well.

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
        float numerator = 1, denominator = 3;
        cout<<(numerator/denominator)<<"\n";
        cout<<setprecision(4)<<(numerator/denominator)<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    0.333333
    0.3333

Implementation of manipulators

All of the manipulators are defined as functions e.g. the manipulator boolalpha is defined as:

    inline ios_base& boolalpha(ios_base& __base)
    {
        __base.setf(ios_base::boolalpha);
        return __base;
    }

So a statement, cout << boolalpha, is interpreted as cout.operator<<(boolaplha). Since boolapha is defined as an function, so the insertion operator in cout< is overloaded to recieve a function pointer as well.

    template<typename _CharT, typename _Traits>
    class basic_ostream : virtual public basic_ios<_CharT, _Traits>
    {
        public:
            ...
            __ostream_type& operator<<(__ostream_type& (*__pf)(__ostream_type&))
            {
                __pf(*this);
                return *this;
            }
            __ostream_type& operator<<(__ios_type& (*__pf)(__ios_type&))
            {
                __pf(*this);
                return *this;
            }
            __ostream_type& operator<<(ios_base& (*__pf) (ios_base&))
            {
                __pf(*this);
                return *this;
            }
            ...
    }

The overloaded operator function simply calls the function pointer with the cout instance as the argument. Therefore, cout.operator<<(boolalpha) ends up in calling boolalpha(cout).

However, things are a little bit different for the manipulators which receive arguments e.g. precision which is defined as

    inline streamsize
    precision(streamsize __prec)
    {
        streamsize __old = _M_precision;
        _M_precision = __prec;
        return __old;
    }

Therefore, for manipulators with agruments, not only the instance of cout needs to be passed but also the precision value. Also, the precision function does not return the instance of ostream class, therefore it cannot be directly called, therefore the new function setprecision is defined which can be used along with insertion operator.

    inline _Setprecision setprecision(int __n)
    {
        _Setprecision __x;
        __x._M_n = __n;
        return __x;
    }

The function setprecision creates a instance of another class which stores the precision value. This instance is passed to the overloaded insertion operator as the argument which cals the precision function with the precision value. Therefore, the statement cout << setprecision(4) gets evaluated like this.

    1. cout << setprecision(4) statement is encountered and function setprecision(4) is called.
    2. Function setprecision creates an instance of _Setprecision class and stores the value 4 in that instance. This instance of _Setprecision class is then returned.
      1. inline _Setprecision setprecision(int __n)
      2. {
      3. _Setprecision __x;
      4. __x._M_n = __n;
      5. return __x;
      6. }
    3. The function cout.operator<<(setprecision(4)) gets evaluated as operator<<(cout, instance of _Setprecision) and the following global function for the overloaded insertion operator gets called
      1. template<typename _CharT, typename _Traits>
      2. inline basic_ostream<_CharT,_Traits>&
      3. operator<<(basic_ostream<_CharT,_Traits>& __os, _Setprecision __f)
      4. {
      5. __os.precision(__f._M_n);
      6. return __os;
      7. }
    4. The overloaded operator function, calls the precision function from the cout, by passing the precsion stored in the instance of _Setprecision instance.

Formatting with input streams

Most of the examples shown above were related to output stream. The formatting control flags and manipulators can also we used with input stream or cin as well.

The formatted cin input functions skip over the whitespaces in the beginning of the input stream. This behaviour can be changed using the ios_base::skipws flag.

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
        char name[20];
        cout<<"Enter name ";
        cin.unsetf(ios_base::skipws);
        cin.getline(name,20);
        cout<<"You entered "<<name<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    Enter name      John
    You entered      John

The insertion operator >> does not have the concept of destination boundaries. This can lead to overflow in the destination. e.g. if the variable <name is defined as name[5], then it is possible to enter 10 characters with the statement cin>>name. This will result in memory corruption. Using the width manipulator we can tell the input stream to transfer only specified amount of bytes to the destination.

    #include <iostream>
    #include <iomanip>
    using namespace std;
    int main()
    {
        char name[5];
        cin.width(5);
        cin>>name;
        cout<<"You entered "<<name<<'\n';
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    Smithers
    You entered Smit

We can also set the ios_base::boolalpha flag to indicate taht boolean flag input should be taken as true and false instead of 0 and 1.

    #include <iostream>
    using namespace std;
    int main()
    {
        bool flag = true;
        cin.setf(ios_base::boolalpha);
        cin>>flag;
        if (!cin.good())
            cout<<"You entered a bad value\n";
        else 
            cout<<"You entered "<<flag<<"\n";
        return 0;
    }
    $ g++ format.cc -o format
    $ ./format 
    true
    You entered 1
    $ ./format 
    false
    You entered 0
    $ ./format 
    yes
    You entered a bad value
    $ ./format 
    1
    You entered a bad value

Formatted functions

One point to be noted is that the formatting functions, flags, and manipulators only affect the behavior of formatted functions only. For instance the ios_base::skipws flag would only affect the formatted functions like cin>>, cin.getline only. The unformatted functions like cin.get would not be impacted by these flags.