12

In python, the following instruction: print 'a'*5 would output aaaaa. How would one write something similar in C++ in conjunction with std::ostreams in order to avoid a for construct?

ildjarn
  • 59,718
  • 8
  • 115
  • 201
Mihai Bişog
  • 968
  • 9
  • 23
  • I just want to point out the rap I got on trying to introduce something like `"abc"_s * 3` or `std::string ("abc") * 3` to mean `"abcabcabc"` on [this question](http://stackoverflow.com/questions/10591262/why-doesnt-stdstring-define-multiplication-or-literals). – chris Jul 10 '12 at 20:50
  • @chris: that's partly because people don't understand that overloading `operator*(string, size_t)` for `string` is *exactly* as bad (or good) as overloading `operator+(string, string)`. No better nor worse - the meaning of multiplication by a natural number as repeated addition is fundamental mathematics, there's no excuse for misunderstanding one but not the other. It's probably also partly because your question complains about the standard and proposes a change to it (neither of which is on topic) in addition to asking a question about the motivation :-p – Steve Jessop Jul 11 '12 at 00:21

4 Answers4

34

The obvious way would be with fill_n:

std::fill_n(std::ostream_iterator<char>(std::cout), 5, 'a');

Another possibility would be be to just construct a string:

std::cout << std::string(5, 'a');
Cody Gray
  • 222,280
  • 47
  • 466
  • 543
Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
  • Is there a specific reason that you don't use an `ostreambuf_iterator`? – Columbo May 24 '15 at 12:41
  • @Columbo: None, other than not really wanting to get into explaining the difference between ostream_iterator and ostreambuf_iterator to somebody coming from Python who (in the end) probably doesn't care about the difference (though, of course, if anybody had asked, I'd probably have referred them to [Xeo's answer](http://stackoverflow.com/a/10564093/179910). – Jerry Coffin May 24 '15 at 18:53
  • 1
    Perhaps surprisingly, **the former results in significantly more efficient object code** on both GCC and Clang. Not only can they unroll the `std:fill_n` operation for a stream, but, more importantly, it avoids the dynamic memory allocation required to construct (and then destroy) a string. (Why they cannot elide the dynamic memory allocation for a compile-time constant string... I'm sure there's a good reason...) – Cody Gray Oct 02 '20 at 21:35
  • @CodyGray: If you're seeing a dynamic allocation for a string of length 5 (compile time constant or otherwise), you should get a better implementation. Short string optimization has been well known for decades now. Admittedly, gcc took a *long* time to add it, but even it's been doing it for a fair length of time now. – Jerry Coffin Oct 04 '20 at 04:09
5

Use some tricky way: os << setw(n) << setfill(c) << ""; Where n is number of char c to write

PiotrNycz
  • 20,687
  • 7
  • 55
  • 102
  • 1
    Tricky and problematic, since the fill character doesn't reset automatically when you're done. – Jerry Coffin Jul 10 '12 at 21:01
  • @Jerry that is true. But it is not a serious issue since `setfill(' ')` after works here. BTW solution with fill_n can be broken by `os << setw(5) << left << fill_n(...)` - producing `a aaaa` :D... – PiotrNycz Jul 11 '12 at 08:26
2

You can do something like that by overloading the * operator for std::string. Here is a small example

#include<iostream>
#include<string>
std::string operator*(const std::string &c,int n)
{
    std::string str;
    for(int i=0;i<n;i++)
    str+=c;
    return str;
}
int main()
{
    std::string str= "foo";
    std::cout<< str*5 <<"\n";
}
nims
  • 3,381
  • 1
  • 21
  • 27
2

In C++20 you'll be able to use std::format to do this:

std::cout << std::format("{:a<5}", "");

Output:

aaaaa

In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):

fmt::print("{:a<5}", "");

Disclaimer: I'm the author of {fmt} and C++20 std::format.

vitaut
  • 37,224
  • 19
  • 144
  • 248