std::vector to string with custom delimiter

前端 未结 9 1111
独厮守ぢ
独厮守ぢ 2020-12-03 16:42

I would like to copy the contents of a vector to one long string with a custom delimiter. So far, I\'ve tried:

// .h
string getLabe         


        
相关标签:
9条回答
  • 2020-12-03 17:08

    Use delimiter.c_str() as the delimiter:

    copy(x.begin(),x.end(), ostream_iterator<int>(s,delimiter.c_str()));
    

    That way, you get a const char* pointing to the string, which is what ostream_operator expects from your std::string.

    0 讨论(0)
  • 2020-12-03 17:08
    int array[ 6 ] = { 1, 2, 3, 4, 5, 6 };
    std::vector< int > a( array, array + 6 );
    stringstream dataString; 
    ostream_iterator<int> output_iterator(dataString, ";"); // here ";" is delimiter 
    std::copy(a.begin(), a.end(), output_iterator);
    cout<<dataString.str()<<endl;
    

    output= 1;2;3;4;5;6;

    0 讨论(0)
  • 2020-12-03 17:13

    C++11:

    vector<string> x = {"1", "2", "3"};
    string s = std::accumulate(std::begin(x), std::end(x), string(),
                                    [](string &ss, string &s)
                                    {
                                        return ss.empty() ? s : ss + "," + s;
                                    });
    
    0 讨论(0)
  • 2020-12-03 17:18

    Another way to do it:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <sstream>
    using namespace std;
    
    template <typename T>
    string join(const T& v, const string& delim) {
        ostringstream s;
        for (const auto& i : v) {
            if (&i != &v[0]) {
                s << delim;
            }
            s << i;
        }
        return s.str();
    }
    
    int main() {
        cout << join(vector<int>({1, 2, 3, 4, 5}), ",") << endl;
    }
    

    (c++11 range-based for loop and 'auto' though)

    0 讨论(0)
  • 2020-12-03 17:21

    I know this is an old question, but I have a similar problem and none of the above answers suits all my needs, so I'll post here my solution.

    My requirements are:

    • I need a generic solution able to work with any iterable container and with any data type, of course for custom data types you'll have to provide a suitable operator<<()
    • I need an easy way to apply transforms to the data (for example, by default int8_t and uint8_t are handled as chars by std::stringstream: maybe this is what you want or maybe not, so I want to be able to make this choice)
    • I want to be able to specify the delimiter as a string literal, but also accept chars and std::strings
    • I like to have the ability to add enclosing characters, but this is probably very personal taste

    This assumes C++11. I choose to use std::stringstream because it implements a standard but still customizable way to convert something to a string. Any comments are very welcome.

    #include <iterator>
    #include <sstream>
    #include <string>
    #include <iostream> // used only in main
    #include <vector> // used only in main
    
    template< typename T >
    typename std::iterator_traits< T >::value_type
    identity(typename std::iterator_traits< T >::value_type v) {
      return v;
    }
    
    template< typename T > using IdentityType = decltype(identity< T >);
    
    template< class InItr,
              typename StrType1 = const char *,
              typename StrType2 = const char *,
              typename StrType3 = const char *,
              typename Transform = IdentityType< InItr > >
    std::string join(InItr first,
                     InItr last,
                     StrType1 &&sep = ",",
                     StrType2 &&open = "[",
                     StrType3 &&close = "]",
                     Transform tr = identity< InItr >) {
    
      std::stringstream ss;
    
      ss << std::forward< StrType2 >(open);
    
      if (first != last) {
    
        ss << tr(*first);
    
        ++first;
      }
    
      for (; first != last; ++first)
        ss << std::forward< StrType1 >(sep) << tr(*first);
    
      ss << std::forward< StrType3 >(close);
    
      return ss.str();
    }
    
    
    int main(int argc, char** argv) {
    
      const std::vector< int > vec{2, 4, 6, 8, 10};
    
      std::cout << join(vec.begin(), vec.end()) << std::endl;
      std::cout << join(vec.begin(), vec.end(), "|", "(", ")",
                        [](int v){ return v + v; }) << std::endl;
    
      const std::vector< char > vec2{2, 4, 6, 8, 10};
      std::cout << join(vec2.begin(), vec2.end()) << std::endl;
      std::cout << join(vec2.begin(), vec2.end(), "|", "(", ")",
              [](char v){ return static_cast<int>(v); }) << std::endl;
    }
    

    outputs something like:

    [2,4,6,8,10]
    (4|8|12|16|20)
    [<unprintable-char>,<unprintable-char>,<unprintable-char>,
    ]
    (2|4|6|8|10)
    
    0 讨论(0)
  • 2020-12-03 17:22
    std::string Gesture::getLabeledPointsString(const std::string delimiter) {
      return boost::join(getLabeledPoints(), delimiter);
    }
    

    I am not that convinced about introducting getLabeledPointsString at this point ;)

    0 讨论(0)
提交回复
热议问题