Search code examples
c++coutostreamsetw

setw within a function to return an ostream


here is my function

ostream margain(std::string firstWord)
{
    ostream x;
    x << std::setw(20) << firstWord;
    return x;
}

in main I want to use the function as follow

std::cout<< margain("start") << "````````````````````````````````````" << std::endl;
// print things out
//then
std::cout<< margain("End") << "````````````````````````````````````" << std::endl;

I get the output, start or end is not shown, and the return value is

0````````````````````````````````````

how can I fix it? and why?

Edit: I know that the function is what causing that, because if I add this

cout << std::setw(20) << firstWord; in the function, It prints right,

I fixed it, not the best way, but as

calling the function as

margain(std::cout, "End") << "~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~" << endl;

the function looks like

ostream& margain(ostream& stream, std::string firstWord)
{
    stream << std::left << std::setw(10) << firstWord;
    return stream;
}

anyone know better way?


Solution

  • You are printing the value of the ostream, not value of firstword. The ostream x in this case is an unopened stream, so it doesn't "do" anything. Because the compiler allows to conversion to either bool (C++11) or void * (before C++11), the "value" from that conversion is printed. Note that any operations on x will not affect cout.

    The easiest solution, I would think is to actually add std::setw(20) to your output line:

    std::cout<< std::setw(20 << "End" << "````````````````````````````````````" << std::endl;
    

    The other choice would be to pass the std::cout to margain, and return the std::string, something like this:

    std::string margain(ostream& x, const std::string& firstWord)
    {
        x << std::setw(20);
        return firstWord;
    }
    

    then you could do:

    std::cout<< margain(cout, "start") << "````````````````````````````````````" << std::endl;
    

    But it's not exactly flexible or "neat".

    The third option is of course to have a MarginString class:

    class MarignString
    {
      private:
         int margin;
         std::string str;
      public:
         MarginString(int margin, std::string str) margin(margin), str(str) {}
         operator std::string() { return str; }
         friend std::ostream& operator(std::ostream& os, const MarginString& ms);
     };
    
    
     std::ostream& operator(std::ostream& os, const MarginString& ms)
     {
         os << std::setw(ms.margin) << ms.str;
         return os;
     }
    
     ...
     std::cout<< MarginString(20, "start") << "````````````````````````````````````" << std::endl;
    

    Note that this last way is probably not that great either... ;)