这是我的条目:
template <typename Container, typename InputIter, typename ForwardIter>
Container
split(InputIter first, InputIter last,
ForwardIter s_first, ForwardIter s_last)
{
Container output;
while (true) {
auto pos = std::find_first_of(first, last, s_first, s_last);
output.emplace_back(first, pos);
if (pos == last) {
break;
}
first = ++pos;
}
return output;
}
template <typename Output = std::vector<std::string>,
typename Input = std::string,
typename Delims = std::string>
Output
split(const Input& input, const Delims& delims = " ")
{
using std::cbegin;
using std::cend;
return split<Output>(cbegin(input), cend(input),
cbegin(delims), cend(delims));
}
auto vec = split("Mary had a little lamb");
第一个定义是采用两对迭代器的STL样式泛型函数。第二个是一个方便的函数,可以让你不用自己做所有的开始和结束。例如,如果要使用列表,还可以将输出容器类型指定为模板参数。
它之所以优雅(IMO),是因为与其他大多数答案不同,它不限于字符串,而是可以与任何STL兼容的容器一起使用。在不更改上述代码的情况下,您可以说:
using vec_of_vecs_t = std::vector<std::vector<int>>;
std::vector<int> v{1, 2, 0, 3, 4, 5, 0, 7, 8, 0, 9};
auto r = split<vec_of_vecs_t>(v, std::initializer_list<int>{0, 2});
这将在每次遇到0或2时将向量v分割成单独的向量。
(还有一个额外的好处,即使用字符串,这个实现比基于strtok()和getline()的版本更快,至少在我的系统上是这样。)