7
printf("%-8s - %s\n", c->name ? c->name : "", c->help);
nicael
  • 18,550
  • 13
  • 57
  • 90

2 Answers2

12

I think what you're looking for is

cout << left << setw(8) << (c->name ? c->name : "") << " - " << c->help << endl;

The left and setw(8) manipulators together have the same effect as the %-8s formatting specifier in printf. You will need to #include <iomanip> in order for this to work, though, because of the use of setw.

EDIT: As Matthieu M. pointed out, the above will permanently change cout so that any padding operations print out left-aligned. Note that this isn't as bad as it might seem; it only applies when you explicitly use setw to set up some padding. You have a few options for how to deal with this. First, you could just enforce the discipline that before using setw, you always use either the left or right manipulators to left- or right-align the text, respectively. Alternatively, you can use the flags and setf function to capture the current state of the flags in cout:

ios_base::fmtflags currFlags = cout.flags();
cout << left << setw(8) << (c->name ? c->name : "") << " - " << c->help << endl;
cout.setf(currFlags, ios_base::adjustfield);

This works in three steps. The first line reads the current formatting flags from cout, including how it's currently aligning padded output. The second line actually prints out the value. Finally, the last line resets cout's output flags for internal alignment to their old value.

Personally, I think the first option is more attractive, but it's definitely good to know that the second one exists since it's technically more correct.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 8
    Uglyness! My eyes! THEY BURN! +1 – Marlon Feb 11 '11 at 07:41
  • 4
    @Marlon- I've never found a single good I/O library with formatting that doesn't cause eyes to burn. I personally like this version more than the `printf` because it's a bit clearer with what it's doing, even if it is a lot more verbose. Also, I once broke my comma/left-angle-brace key, and so for the longest time I dreaded ever having to type something like this out. :-) – templatetypedef Feb 11 '11 at 07:43
  • @Marlon A few line breaks would help relieve some of the pain. I also recommend you take Aspirin ++. – Mateen Ulhaq Feb 11 '11 at 07:50
  • @templatetypedef: I don't think this is clearer because it doesn't put the format specifier in one place for quick overview. This can be a pain to maintain when you only want an extra space somewhere in the middle. Still, +1. – Fred Foo Feb 11 '11 at 07:52
  • Note that the "<< endl" at the end of the line will also flush the stream, which is not the same as a simple "\n". For a complete equivalent for what you wrote, use "<< "\n"" instead of "<< endl". Read more here: http://stackoverflow.com/questions/213907/c-stdendl-vs-n – gnobal Feb 11 '11 at 07:58
  • @templatetypedef: unfortunately it's not equivalent. Manipulators are pretty long lived, and therefore all subsequent inputs will be affected by `left`. You thus need to restore the previous manipulator. That's the most important issue with IO Streams, manipulators introduce global state (eurk). – Matthieu M. Feb 11 '11 at 08:43
  • @Matthieu M.: You are correct that `left` will stick around afterwards. However, I don't believe that entirely invalidates this answer. First, if you enforce the discipline of always specifying what sort of alignment you want before using `setw`, this is irrelevant. Second, `left` only has an effect when `setw` is used, so it will not adversely affect the output for other operations, especially if the aforementioned discipline is used. Also, is there something specifically I can do to get you to remove the downvote? I'd appreciate any suggestions on how to improve my answer. – templatetypedef Feb 11 '11 at 08:56
  • @templatetypedef: show how to capture/restore the previous setting, it's something that really catches beginners unaware. – Matthieu M. Feb 11 '11 at 09:09
  • @Matthieu: I noticed, removed my comment. Second error I catch on fredosaurus in a week... – Fred Foo Feb 11 '11 at 09:11
  • @larsmans: personally, I'm hardpressed to ever remember... I've got a simple .cpp file I keep on the side to test this kind of things quickly :) – Matthieu M. Feb 11 '11 at 09:13
  • @Matthieu: I just never use the manipulators except with short-lived streams. Otherwise, it's `boost::format` all the way. – Fred Foo Feb 11 '11 at 09:15
  • @Matthieu M.- Can you check over what I have and confirm that it's correct? I think this works out correctly. – templatetypedef Feb 11 '11 at 09:20
  • @larsmans: the only issue with Boost.Format is that the compiler does not warn if by mistake you didn't provided enough parameters (or you provided too much) or if the type mismatched... `printf` (and co) is usually checked by compilers (though only usable for PODs). – Matthieu M. Feb 11 '11 at 09:20
  • @templatetypedef: looks good (ahem... *correct*), I've removed my downvote :) I don't really feel like upvoting though, because of the messy syntax this impose (nothing against you, more of a peeve against the IOStream library). – Matthieu M. Feb 11 '11 at 09:24
  • @Matthieu M.- Thanks for looking over that so quickly and for catching that slip-up. And no offense taken for not upvoting; it definitely is messy! – templatetypedef Feb 11 '11 at 09:25
  • The use of `ios_base::fmtflags` is not exception-safe in general. It's better to use the Boost ios state saver for this purpose (but then, why not use `format`?). – Fred Foo Feb 11 '11 at 11:00
  • @larsmans- True, though the question was mostly on how to use `cout` and so I assumed that the OP's question relates mostly to standard C++ (aka without Boost). Making this Boostier certainly wouldn't hurt, but I think it's beyond the scope of the OP's question. – templatetypedef Feb 11 '11 at 11:07
  • @Jörgen Sigvardsson: "Not trying to start a pseudo religious debate, but [starts a pseudo-religious debate]". In other words, "I know it's wrong, but what the heck, I'll do it anyway"? Please don't do that. – Piskvor left the building Feb 11 '11 at 12:03
9

If you've got the Boost libraries:

std::cout << boost::format("%-8s - %s\n") % (c->name ? c->name : "") % c->help;
Fred Foo
  • 355,277
  • 75
  • 744
  • 836