Printing lists with commas C++

后端 未结 28 1786
时光取名叫无心
时光取名叫无心 2020-11-22 03:33

I know how to do this in other languages, but not C++, which I am forced to use here.

I have a Set of Strings that I\'m printing to out in a list, and they need a co

相关标签:
28条回答
  • 2020-11-22 03:53

    There are lots of clever solutions, and too many that mangle the code beyond hope of salvation without letting the compiler do its job.

    The obvious solution, is to special-case the first iteration:

    bool first = true;
    for (auto const& e: sequence) {
       if (first) { first = false; } else { out << ", "; }
       out << e;
    }
    

    It's a dead simple pattern which:

    1. Does not mangle the loop: it's still obvious at a glance that each element will be iterated on.
    2. Allows more than just putting a separator, or actually printing a list, as the else block and the loop body can contain arbitrary statements.

    It may not be the absolutely most efficient code, but the potential performance loss of a single well-predicted branch is very likely to be overshadowed by the massive behemoth that is std::ostream::operator<<.

    0 讨论(0)
  • 2020-11-22 03:53

    My typical method for doing separators (in any language) is to use a mid-tested loop. The C++ code would be:

    for (;;) {
       std::cout << *iter;
       if (++iter == keywords.end()) break;
       std::cout << ",";
    }
    

    (note: An extra if check is needed prior to the loop if keywords may be empty)

    Most of the other solutions shown end up doing an entire extra test every loop iteration. You are doing I/O, so the time taken by that isn't a huge problem, but it offends my sensibilities.

    0 讨论(0)
  • 2020-11-22 03:53

    Following should do:-

     const std::vector<__int64>& a_setRequestId
     std::stringstream strStream;
     std::copy(a_setRequestId.begin(), a_setRequestId.end() -1, std::ostream_iterator<__int64>(strStream, ", "));
     strStream << a_setRequestId.back();
    
    0 讨论(0)
  • 2020-11-22 03:54

    Use an 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 
    

    Usage would be something like:

    #include "infix_iterator.h"
    
    // ...
    std::copy(keywords.begin(), keywords.end(), infix_iterator(out, ","));
    
    0 讨论(0)
  • 2020-11-22 03:55

    Assuming a vaguely normal output stream, so that writing an empty string to it does indeed do nothing:

    const char *padding = "";
    for (auto iter = keywords.begin(); iter != keywords.end(); ++iter) {
        out << padding << *iter;
        padding = ", "
    }
    
    0 讨论(0)
  • 2020-11-22 03:58

    You can use a do loop, rewrite the loop condition for the first iteration, and use the short-circuit && operator and the fact that a valid stream is true.

    auto iter = keywords.begin();
    if ( ! keywords.empty() ) do {
        out << * iter;
    } while ( ++ iter != keywords.end() && out << ", " );
    out << endl;
    
    0 讨论(0)
提交回复
热议问题