A few weeks back, I posited the question, "What is the best way to format a comma delimited list?"
After seeing all of the succinct ways to accomplish this in other languages, I got a little jealous and decided to write this C++ algorithm which acts about the same.
I feel like there must be a c++ standard library way of doing this that I'm some how overlooking.
template <typename InItr> std::string join(InItr begin, InItr end, const std::string &joiner) { std::string ret; while (begin != end) { std::stringstream ss; ss << *begin; ret += ss.str(); ++begin; if (begin != end) { ret += joiner; } } return ret; }
Usage:
//With an array: int vals[] = {1,17,9}; std::cout << join(&vals[0], &vals[sizeof(vals)/sizeof(int)], ", ") << std::endl; //With a vector: std::vector<int> vec; vec.push_back(1); vec.push_back(17); vec.push_back(9); std::cout << join(vec.begin(), vec.end(), ",") << std::endl;
Comments
handle last element
I prefer to erase the joiner at end
std::string ret;
std::stringstream ss;
while (begin != end) {
ss << *begin++ << joiner;
}
ret = ss.str();
ret.erase(ret.size() - joiner.size(), joiner.size());
return ret;
I, embarrasedly forgot to
I, embarrasedly forgot to handle "begin == end" case ...
One way
One way more:
std::copy(vec.begin(), --vec.end(), std::ostream_iterator(std::cout, ","));
std::cout << vec.back();
Creative, but not there
Your version has two problems:
A corrected version would require several checks.
Another way is to use Boost's Spirit.Karma library.
Another way is to use Boost's Spirit.Karma library.
Here an example to format an container into a comma separated list:
Where 'c' is the container.
Have a look at the full example code at http://svn.boost.org/svn/boost/trunk/libs/spirit/example/karma/basic_fac...