views:

243

answers:

4

I want to create a function that will take a string and an integer as parameters and return a string that contains the string parameter repeated the given number of times.

For example:

std::string MakeDuplicate( const std::string& str, int x )
{
    ...
}

Calling MakeDuplicate( "abc", 3 ); would return "abcabcabc".

I know I can do this just by looping x number of times but I'm sure there must be a better way.

+7  A: 

At some point it will have to be a loop. You may be able to hide the looping in some fancy language idiom, but ultimately you're going to have to loop.

John Weldon
+1  A: 

There is an alternative to a loop, its called recursion, and of recursion tail-recursion is the nicest variety since you can theoretically do it till the end of time -- just like a loop :D

p.s., tail-recursion is often syntactic sugar for a loop -- however in the case of procedural languages (C++), the compiler is generally at loss, so the tail-recursion is not optimised and you might run out of memory (but if you wrote a recursion that runs out of memory than you have bigger problems) :D

more downvotes please !!

recursion is obviously not a construct used in computer science for the same job as looping

Hassan Syed
It's elegant, but when somebody types in MakeDuplicate("very long string ... ", 200000) they are gonna cry :)
Skurmedel
Even recursion is often reduced to looping for efficiency...
John Weldon
Looping can be parallelized, but recursion cannot.
Hamish Grubijan
@lp well yes -- I agree (compiler optimization), but if you wrap the recursion in question with another recursion you can paralelise .... and such code in my experience is far more robust -- think Erlang :D
Hassan Syed
C++ does not (generally) optimize tail recursion. You could end up with a stack overflow with such a solution.
Billy ONeal
You could delete your answer instead of asking for more downvotes. Downvotes cost 1 point.
Daniel Daranas
Why should I ? an answer is never complete unless it explores all relevant avenues. I have not even disagreed with the potential pitfalls of recursion...
Hassan Syed
Why is it downvoted? It's ideal answer to demonstrate why elegant recursive solution is not suitable (for large x at least).
MaR
+18  A: 

I don't see a problem with looping, just make sure you do a reserve first:

std::string MakeDuplicate( const std::string& str, int x )
{
    std::string newstr;
    newstr.reserve(str.length()*x); // prevents multiple reallocations

    // loop...

    return newstr;
}
luke
+1 Was just about to post about reserving the memory.
MikeSep
Although it should read newstr.reserve(...)
MikeSep
Thanks MikeSep, nice catch. Corrected.
luke
Looping is fine, its just one of those things that 'feels' like there would be a more explicit way of achieving it, but maybe there isn't.
Richard
I don't think there's an an idiomatic way of doing what you ask in c++.
luke
A slightly more efficient version would probably be to begin with copying the actual string, and then looping `x-1` times. Although it would require a check for `0` to avoid an unnecessary copy.
Matthieu M.
Matthieu M.- I had thought about that, but you'd still probably be doing two memory allocations: one when you construct the string, and another to make it the max size. One upfront allocation for the whole thing is probably faster.
luke
+4  A: 

For small 'x' simple loop is your friend. For large 'x and relatively short 'str' we can think of a "smarter" solution by reusing already concatenated string.

std::string MakeDuplicate( const std::string& str, unsigned int x ) {

  std::string newstr;
  if (x>0) {
    unsigned int y = 2;
    newstr.reserve(str.length()*x);  
    newstr.append(str);
    while (y<x) {
      newstr.append(newstr);
      y*=2;
    }
    newstr.append(newstr.c_str(), (x-y/2)*str.length());
  }
  return newstr;
}

Or something like that :o) (I think it can be written in a nicer way but idea is there).

EDIT: I was intersted myself and did some tests comparing three solutions on my notebook with visual studio (reuse version, simple loop with preallocation, simple copy&loop-1 without preallocation). Results as expected: for small x(<10) preallocation version is generally fastest, no preallocation was tiny bit slower, for larger x speedup of 'reuse' version is really significant (log n vs n complexity). Nice, I just can't think of any real problem that could use it :o)

MaR