setw within a function to return an ostream

1k views Asked by At

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?

2

There are 2 answers

0
Mats Petersson On BEST ANSWER

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... ;)

2
David G On
struct margin
{
    margin(std::string word) : word(word) { }

    friend std::ostream& operator <<(std::ostream& os, margin const& m)
    {
         return os << std::setw(20) << m.word;
    }

private:
    std::string word;
};