有没有办法使用std :: ostream_iterator(或类似的),以便不为最后一个元素放置分隔符?
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
std::vector<int> ints = {10,20,30,40,50,60,70,80,90};
std::copy(ints.begin(),ints.end(),std::ostream_iterator<int>(std::cout, ","));
}
将打印
10,20,30,40,50,60,70,80,90,
我正试图避免落后的分隔符。我想打印
10,20,30,40,50,60,70,80,90
当然,你可以使用一个循环:
for(auto it = ints.begin(); it != ints.end(); it++){
std::cout << *it;
if((it + 1) != ints.end()){
std::cout << ",";
}
}
但是考虑到基于C ++ 11范围的循环,跟踪位置是很麻烦的。
int count = ints.size();
for(const auto& i : ints){
std::cout << i;
if(--count != 0){
std::cout << ",";
}
}
我愿意使用Boost。我查看了boost::algorithm::join(),但是需要将整数的副本复制到字符串中,因此它是一个双线程。
std::vector<std::string> strs;
boost::copy(ints | boost::adaptors::transformed([](const int&i){return boost::lexical_cast<std::string>(i);}),std::back_inserter(strs));
std::cout << boost::algorithm::join(strs,",");
理想情况下,我只想使用std :: algorithm,而不是该范围内最后一项的分隔符。
谢谢!
答案 0 :(得分:6)
@Cubbi在评论中指出,这正是infix_iterator所做的
// 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
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
std::vector<int> ints = {10,20,30,40,50,60,70,80,90};
std::copy(ints.begin(),ints.end(),infix_ostream_iterator<int>(std::cout,","));
}
打印:
10,20,30,40,50,60,70,80,90
答案 1 :(得分:4)
copy
可以实现为:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++result; ++first;
}
return result;
}
ostream_iterator
(输出迭代器)的赋值可以实现为:
ostream_iterator<T,charT,traits>& operator= (const T& value) {
*out_stream << value;
if (delim!=0) *out_stream << delim;
return *this;
}
因此分隔符将附加到输出迭代器的每个赋值。为避免将分隔符附加到最后一个向量元素,应将最后一个元素分配给不带分隔符的输出迭代器,例如:
#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;
}
结果:
10,20,30,40,50,60,70,80,90
答案 2 :(得分:2)
这会更容易。不知道你想要什么
#include<iostream>
#include<algorithm>
#include<vector>
#include<iterator>
int main()
{
std::vector<int> ints={10,20,30,40,50,60,70,80,90};
std::copy(ints.begin(),ints.end(),std::ostream_iterator<int> (std::cout,","));
std::cout<<(char)8;
}
答案 3 :(得分:0)
使用std :: string的success