We need these two opposite operations more or less often. As C++ stl does not provide us these functions, we need to write them ourselves.
template <class T>
string vector_join( const vector<T>& v, const string& token ){
ostringstream result;
for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); i++){
if (i != v.begin()) result << token;
result << *i;
}
return result.str();
}
vector<string> string_split( const string& s, const string& delimiter ){
vector<string> result;
string::size_type from = 0;
string::size_type to = 0;
while ( to != string::npos ){
to = s.find( delimiter, from );
if ( from < s.size() && from != to ){
result.push_back( s.substr( from, to - from ) );
}
from = to + delimiter.size();
}
return result;
}
The functions produce the following results:
string ss[] = { "qwerty", "hello", "world" };
vector<string> v( ss, ss+3 );
vector_join( v, ", ") );//"qwerty, hello, world"
int ii[] = { 111, 222, 333 };
vector<int> vi( ii, ii+3 );
vector_join( vi, "; ") );//"111; 222; 333"
string_split( "qwerty, hello, world", ", " );
//results in [ "qwerty", "hello", "world" ]
string_split( ", , wow, , qwerty, hello, world, ", ", " );
//results in [ "wow", "qwerty", "hello", "world" ]
If we have a space as delimiter, we can split string more efficient way and even make use of templates too
template <class T>
vector<T> string_split( const string& s ){
vector<T> result;
istringstream ss(s);
copy( istream_iterator<T>(ss), istream_iterator<T>(),
back_inserter( result ) );
return result;
}
And the tests:
string_split<float>( "11.1 22.2 33.3" );//[ 11.1, 22.2, 33.3 ]
string_split<int>( "111 222 333" );//[ 111, 222, 333 ]