1

I need to convert an int[] to string. There is std::to_string method but it doesn't take an array as input. So, a for loop is required like here. Is there some method where I can achieve this without an explicit for loop? Like in Java, we can use java.util.Arrays.toString() for this purpose.

EDIT: Any possible way around would be helpful too which solves the issue in an optimized way.

Community
  • 1
  • 1
mibrahimy
  • 722
  • 4
  • 18
  • Poosible Duplicate : https://stackoverflow.com/questions/3619850/converting-an-int-array-to-a-string-array – Harshit kyal Dec 29 '17 at 06:07
  • 1
    There's no standard `join` function, which is how you'd normally turn a collection into a string. It still exists in other libraries of course. – chris Dec 29 '17 at 06:10
  • I am not using Java. The above link doesn't help me. – mibrahimy Dec 29 '17 at 06:10
  • 4
    Eventually there's going to be a loop, whether you write it yourself or it's hidden by a language construct. Write a function, call it, move on. – Retired Ninja Dec 29 '17 at 06:27
  • 3
    Don't confuse short with optimized, especially when you do not know exactly what is happening in the code hidden behind the pretty wrapper. Measure, then optimize. You can't tell that one thing is faster than another without measuring, and you also can't tell if you're focusing on the wrong thing. – Retired Ninja Dec 29 '17 at 07:07
  • 2
    there is `std::for_each` if you want a function look `for` – apple apple Dec 29 '17 at 07:19
  • @Retired Ninja The loop isn't required as I show in my answer, though I doubt my solution will really be faster – papagaga Dec 29 '17 at 10:13

3 Answers3

3

This will do the trick

 #include <iostream>       
 #include <sstream>      
 #include <iterator>       
 #include <algorithm>
 #include <string>

 int main()
 {
      int x[] = {1,2,3,4,5};     // sample array

      std::ostringstream os;
      std::ostream_iterator<int> out(os, " ");
      std::copy(std::begin(x), std::end(x), out);
      std::string result = os.str();
 }

Bear in mind that result will have a trailing space after the last int value. I'll leave removing that as an exercise.

Slightly more cryptically.

      std::ostringstream os;
      std::copy(std::begin(x), std::end(x), std::ostream_iterator<int>(os, " "));
      std::string result = os.str();

In C++, you won't get something exactly like Java, since int [] is more primitive in C++ than in Java. For example, when passed as an argument to a function, an array is converted to pointer to its first element, so the called function does not receive information about number of elements.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • Perhaps, perhaps not. `std::copy` is just a wrapper for a loop. The size of the code is rarely indicative of it's efficiency. I can show you a one liner that's terrible compared to a 30 line unrolled loop. But, what does it matter if neither is in a place that's truly a bottleneck in your code? – Retired Ninja Dec 29 '17 at 07:04
  • @IbrahimYousaf - maybe. That's a quality of implementation concern. There is nothing stopping `std::copy()` using some compiler or machine-specific magic that beats a loop, but equally nothing preventing it. If you want to be sure, benchmark on representative target systems. – Peter Dec 29 '17 at 07:09
  • FWIW, there's an [`ostream_joiner`](http://en.cppreference.com/w/cpp/experimental/ostream_joiner) for the extra space, but it's in a TS. Anyway, it's also possible for a function to get size information when given an array. It simply has to take the array by reference instead of accepting a pointer to the first element. – chris Dec 29 '17 at 07:50
2

You can avoid the loop by using some meta-programming. The idea is to unfold the loop at compile-time:

First, use a reference to avoid an array-to-pointer decay. That way, you can deduce the size of the array. You use the size to generate a compile-time std::size_t sequence going from 0 to size-1 and feed the array and the sequence to an implementation function:

template <std::size_t N>
std::string to_string(int (&array)[N]) {
    return to_string_impl(array, std::make_index_sequence<N>());
}

In that second function, you use parameter pack expansion to generate an unfolded loop:

template <std::size_t N, std::size_t... Ns>
std::string to_string_impl(int (&array)[N], std::index_sequence<Ns...>) {
    std::ostringstream os;
    std::ostream_iterator<int> out(os, " ");
    int dummy[sizeof...(Ns)] = { (os << array[Ns], 0)... };
    /* generates:
       os << array[0]
       ...
       os << array[N-1]
    */
    return os.str();
}

NB: don't forget to include:

#include <iostream>
#include <utility>
#include <sstream>
#include <iterator>

Then you have it:

int main() {
    int arr[] = {1,2,3,4,5};
    std::cout << to_string(arr); // prints "12345"
}
papagaga
  • 1,108
  • 8
  • 14
  • 1
    An interesting solution. However, it should be mentioned that it will only work for arrays which size is known during compilation. – Innokentiy Alaytsev Dec 29 '17 at 10:14
  • @InnokentiyAlaytsev: True, I had forget we have access to run-time sized arrays in C++ too... since C++17? – papagaga Dec 29 '17 at 10:19
  • @papagaga, No runtime-sized arrays yet. There's been an effort to solve the problems involved, but no conclusion has been reached. – chris Dec 29 '17 at 14:50
  • Visual Studio only allows 1024 elements in the array before it says the recursive type is too complex. I was kind of surprised it went that high, it used to fall over much more quickly. Neat trick though. :) – Retired Ninja Dec 29 '17 at 21:27
-2

Try this out

#include <sstream>
#include <string>
#include <iostream>

std::string ToString(int number)
{
    std::string str;
    std::stringstream ssout;
    ssout << number;
    str = ssout.str(); 
    return str;
}
int main()
{
    std::string mystr;
    mystr = ToString(1234);
    std::cout<<mystr<<std::endl;
    getchar();
    return 0;
}
void
  • 376
  • 2
  • 7
  • 18