众所周知,C++一直没有一个官方提供的string split用于分割字符串,在过去(C++20之前)我们可能需要使用std::regex、std::string::find系列方法、甚至是继承自C的strtok函数来自行封装一个split,非常繁琐与不便。
然而,这一切都在C++20中发生了变化。C++20引入了范围库ranges,其中提供的两个范围适配器std::split、std::lazy_split可以使我们以一种更为优雅的形式实现split。x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <concept> #include <ranges> #include <algorithm> #include <format> #include <iostream>
#define stdr std::ranges #define stdrv std::ranges::views
template<template<typename> typename Container = std::vector, typename Arg = std::string_view> auto Split(std::string_view str, std::string_view delimiter) { Container<Arg> myCont; auto temp = str | stdrv::split(delimiter) | stdrv::transform([](auto&& r) { return Arg(std::addressof(*r.begin()), stdr::distance(r)); }); auto iter = std::inserter(myCont, myCont.end()); stdr::for_each(temp, [&](auto&& x) { iter = {x.begin(), x.end()}; }); return myCont; } int main() { std::string str = "Hello233C++20233and233New233Spilt"; std::string delimiter = "233"; auto&& strCont = Split<std::list, std::string>(str, delimiter); stdr::for_each(strCont, [](auto&& x) { std::cout << std::format("{} ", x); }); }
|
PS:std::split与std::lazy_split存在细微区别,在此不作详细说明,感兴趣可以参考:
https://stackoverflow.com/questions/68067612/what-is-the-difference-between-the-split-view-and-the-lazy-split-view-in-c
PS2:C++20没有提供关键的ranges::to函数,导致demo中还需要额外封装并手写for_each来写入数据,等到C++23实装了该函数,split的实现会比现在简洁优雅的多,真正做到方便泛用、无需封装:
1 2 3
| auto&& strCont = str | stdrv::lazy_split(delimiter) | stdr ::to<std::vector<std::string>>;
|
原文链接: https://zhuanlan.zhihu.com/p/474447289