A
Alan Woodland
Hi,
I was looking for a clean, generic way to split strings around a
character using STL algorithms. The best I could manage was this
example, which isn't exactly great to say the least.
#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <iterator>
#include <iostream>
namespace {
template <typename T>
struct SplitHelper {
std::basic_ostringstream<typename T::value_type> next;
std::vector<T> result;
typename T::value_type match;
static bool test(SplitHelper& h, const typename T::value_type c) {
if (c == h.match) {
h.result.push_back(h.next.str());
h.next.str(T());
}
return c == h.match;
}
};
}
std::vector<T> split(const T& str, const typename T::value_type c='/') {
SplitHelper<T> h;
h.match = c;
h.result.reserve(std::count(str.begin(), str.end(), c));
std::remove_copy_if(str.begin(), str.end(),
std:stream_iterator<typename T::value_type>(h.next),
std::bind1st(std:tr_fun(&h.test), h));
h.result.push_back(h.next.str());
return h.result;
}
#include <iostream>
int main() {
const std::string path = "Hello/cruel/world";
const std::vector<std::string>& result = split(path);
std::cout << result.size() << std::endl;
assert(3==result.size());
std::cout << result[0] << std::endl;
std::cout << result[1] << std::endl;
std::cout << result[2] << std::endl;
return 0;
}
Is this really the tidiest way to do this using STL algorithms?
Obviously it wouldn't be hard at all to do just using a for loop and two
pointers, but I was trying to do this 'the STL way'.
Thanks for any suggestions,
Alan
I was looking for a clean, generic way to split strings around a
character using STL algorithms. The best I could manage was this
example, which isn't exactly great to say the least.
#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <iterator>
#include <iostream>
namespace {
template <typename T>
struct SplitHelper {
std::basic_ostringstream<typename T::value_type> next;
std::vector<T> result;
typename T::value_type match;
static bool test(SplitHelper& h, const typename T::value_type c) {
if (c == h.match) {
h.result.push_back(h.next.str());
h.next.str(T());
}
return c == h.match;
}
};
}
std::vector<T> split(const T& str, const typename T::value_type c='/') {
SplitHelper<T> h;
h.match = c;
h.result.reserve(std::count(str.begin(), str.end(), c));
std::remove_copy_if(str.begin(), str.end(),
std:stream_iterator<typename T::value_type>(h.next),
std::bind1st(std:tr_fun(&h.test), h));
h.result.push_back(h.next.str());
return h.result;
}
#include <iostream>
int main() {
const std::string path = "Hello/cruel/world";
const std::vector<std::string>& result = split(path);
std::cout << result.size() << std::endl;
assert(3==result.size());
std::cout << result[0] << std::endl;
std::cout << result[1] << std::endl;
std::cout << result[2] << std::endl;
return 0;
}
Is this really the tidiest way to do this using STL algorithms?
Obviously it wouldn't be hard at all to do just using a for loop and two
pointers, but I was trying to do this 'the STL way'.
Thanks for any suggestions,
Alan