¿Cómo puedo imprimir una lista de elementos separados por comas?

Resuelto quandrum asked hace 14 años • 36 respuestas

Sé cómo hacer esto en otros lenguajes, pero no en C++, que me veo obligado a usar aquí.

Tengo un conjunto de cadenas ( keywords) en las que estoy imprimiendo outcomo una lista, y las cadenas necesitan una coma entre ellas, pero no una coma al final. En Java, por ejemplo, usaría a StringBuildery simplemente eliminaría la coma al final después de haber creado mi cadena. ¿Cómo puedo hacerlo en C++?

auto iter = keywords.begin();
for (iter; iter != keywords.end( ); iter++ )
{
    out << *iter << ", ";
}
out << endl;

Inicialmente intenté insertar el siguiente bloque para hacerlo (moviendo la impresión de coma aquí):

if (iter++ != keywords.end())
    out << ", ";
iter--;
quandrum avatar Aug 17 '10 03:08 quandrum
Aceptado

Utilice un 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 

El uso sería algo como:

#include "infix_iterator.h"

// ...
std::copy(keywords.begin(), keywords.end(), infix_iterator(out, ","));
Jerry Coffin avatar Aug 16 '2010 20:08 Jerry Coffin

En un compilador experimental listo para C++ 17 que estará disponible próximamente, puede usar 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, ", "));
}

Ejemplos en vivo usando GCC 6.0 SVN y Clang 3.9 SVN

TemplateRex avatar Mar 14 '2016 21:03 TemplateRex