Algorithm comma join
stackoverflow Convert vector to delimited string
A
std::copy
+ std::ostream_iterator
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <iostream>
int main()
{
std::vector<int> data = { 42, 1, 2, 3, 4, 5 };
std::ostringstream oss;
std::copy(data.begin(), data.end(), std::ostream_iterator<int>(oss, ";"));
std::string result(oss.str());
std::cout << result << "\n";
}
// g++ test.cpp --std=c++11 -pedantic -Wall
输出如下:
42;1;2;3;4;5;
N.B. In C++11, you can use the more general form
using std::begin;
using std::end;
std::copy(begin(data), end(data), std::ostream_iterator<int>(oss, ";"));
Where the using-declarations are not required if ADL can be used (like in the example above).
NOTE:
完整测试程序:
#include <sstream> #include <string> #include <vector> #include <iterator> #include <iostream> int main() { std::vector<int> data = { 42, 1, 2, 3, 4, 5 }; using std::begin; using std::end; std::ostringstream oss; std::copy(begin(data), end(data), std::ostream_iterator<int>(oss, ";")); std::string result(oss.str()); std::cout << result << "\n"; } // g++ test.cpp --std=c++11 -pedantic -Wall
std::accumulate
NOTE:
1、这种方式是效率较低的
Also possible, but maybe a bit less efficient:
std::string s;
for(auto const& e : v) s += std::to_string(e) + ";";
which can be written via std::accumulate
in <algorithm>
as:
std::string s = std::accumulate(begin(v), end(v), std::string{},
[](std::string r, int p){ return std::move(r) + std::to_string(p) + ";"; });
(IIRC there was some method to eliminate the copying, maybe by taking the lambda-parameter by reference std::string& r
.)
w/o the trailing semi-colon
A version w/o the trailing semi-colon (thanks to Dietmar Kühl):
std::vector<int> data = {42, 1, 2, 3, 4, 5};
std::ostringstream out;
if (!v.empty())
{
std::copy(v.begin(), v.end() - 1, std::ostream_iterator<int>(out, ";"));
out << v.back();
}
std::string result( out.str() );
std::cout << result << "\n";
NOTE:
完整测试程序:
#include <sstream> #include <string> #include <vector> #include <iterator> #include <iostream> int main() { std::vector<int> v = { 42, 1, 2, 3, 4, 5 }; std::ostringstream out; if (!v.empty()) { std::copy(v.begin(), v.end() - 1, std::ostream_iterator<int>(out, ";")); out << v.back(); } std::string result(out.str()); std::cout << result << "\n"; } // g++ test.cpp --std=c++11 -pedantic -Wall
stackoverflow Printing lists with commas C++
A
NOTE:
1、这个回答的作者并没有给出解释,在stackoverflow std::ostream_iterator prevent last item from using the delimiter [duplicate] # A 中给出的回答可以给出理解下面code的关键,下面收录了。
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <iostream>
// infix_iterator.h
//
// Lifted from Jerry Coffin's 's prefix_ostream_iterator
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>
template<class T, class charT = char, class traits = std::char_traits<charT> >
class infix_ostream_iterator: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
std::basic_ostream<charT, traits> *os; // 输出流
charT const *delimiter; // 分隔符
bool first_elem; // 是否是第一个元素的标志
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT, traits> ostream_type;
infix_ostream_iterator(ostream_type &s) :
os(&s), delimiter(0), first_elem(true)
{
}
infix_ostream_iterator(ostream_type &s, charT const *d) :
os(&s), delimiter(d), first_elem(true)
{
}
infix_ostream_iterator<T, charT, traits>& operator=(T const &item)
{
// Here's the only real change from ostream_iterator:
// Normally, the '*os << item;' would come before the 'if'.
if (!first_elem && delimiter != 0)
*os << delimiter;
*os << item;
first_elem = false;
return *this;
}
infix_ostream_iterator<T, charT, traits>& operator*()
{
return *this;
}
infix_ostream_iterator<T, charT, traits>& operator++()
{
return *this;
}
infix_ostream_iterator<T, charT, traits>& operator++(int)
{
return *this;
}
};
#endif
int main()
{
std::string keywords("hello world");
std::ostringstream out;
// ...
std::copy(keywords.begin(), keywords.end(), infix_ostream_iterator<char>(out, ","));
std::cout << out.str() << std::endl;
}
// g++ test.cpp --std=c++11 -pedantic -Wall
输出如下:
h,e,l,l,o, ,w,o,r,l,d
A
In an experimental C++17 ready compiler coming soon to you, you can use std::experimental::ostream_joiner
:
#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
int main()
{
int i[] = {1, 2, 3, 4, 5};
std::copy(std::begin(i),
std::end(i),
std::experimental::make_ostream_joiner(std::cout, ", "));
}
Live examples using GCC 6.0 SVN and Clang 3.9 SVN
stackoverflow std::ostream_iterator prevent last item from using the delimiter [duplicate]
A
copy
could be implement as:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
The assignment to the ostream_iterator
(output iterator) could be implemented as:
ostream_iterator<T,charT,traits>& operator= (const T& value) {
*out_stream << value;
if (delim!=0) *out_stream << delim;
return *this;
}
So the delimiter will be appended on every assignment to the output iterator. To avoid the delimiter being appended to the last vector element, the last element should be assigned to an output iterator without delimiter, for example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::vector<int> ints = {10,20,30,40,50,60,70,80,90};
std::copy(ints.begin(), ints.end()-1, std::ostream_iterator<int>(std::cout, ","));
std::copy(ints.end()-1, ints.end(), std::ostream_iterator<int>(std::cout));
std::cout << std::endl;
return 0;
}
Results in:
10,20,30,40,50,60,70,80,90