Search code examples
c++stlformatwidthostringstream

how to truncate width of integral types with std::ostringstream?


Say you have something like:

std::ostringstream oss;
int value(42);
oss.fill('0');
oss << std::setw(3) << value;
cout << oss.str();

OUTPUT: 042

This output is because std::setw ensures a minimum width and we told the stream to fill with 0 however how do you do the opposite and specify a maximum width so that display will be truncated in STL and native C++ preferably ...

Currently I have something which I consider an ugly and inefficient hack:

std::ostringstream oss;
int value(1239999);
oss.fill('0');
oss << std::setw(3) << boost::lexical_cast<std::string, int>(value).substr(0, 3);
cout << oss.str();

OUTPUT: 123

I've looked at boost::format but it's the same story there as far as I can tell there is no way to do this "prettily" ... any suggestions?

UPDATE: std::ostringstream and STL streams in general are known to perform slowly compared to other containers and template objects of STL. Perhaps I would be better off making a message queue object which wraps and internally uses a std::queue and then just use sprintf_s for formatting purposes?


Solution

  • The stream formatting capabilities are not intended as a general purpose string manipulation package. What you are trying to do does not make much sense numerically, so it is not supported - using the substring or similar functions is the way to go. You can (and should, if you need this in more than one place) write your own function to do the job.

    Something like:

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <iomanip>
    
    void First3( std::ostream & os, int value ) {
        std::ostringstream oss;
        oss.fill('0');
        oss << std::setw(3) << value;
        os << oss.str().substr( 0, 3 );
    }
    
    int main() {
        First3( std::cout, 1239999 );
        std::cout << " ";
        First3( std::cout, 1 );
    }
    

    Note there is no need for Boost to be used.