限制std::views::split生成的子区间数量
#include <iomanip>
#include <iostream>
#include <ranges>
#include <string_view>
int main()
{
using std::operator""sv;
constexpr auto words{"Hello C++ 20!"sv};
for (const auto word : std::views::split(words, ' '))
std::cout << std::quoted(std::string_view(word)) << ' ';
std::cout << '\n';
}
在 此链接 的输出是 "Hello" "C++" "20!"。
如何使用 n 限制分割数量并获得输出:"Hello" "C++ 20!"(使用 n = 1,从开头开始单次分割,第一子区间是 Hello,第二子区间是第一個空格之后的所有字符。)
这可以在C++26中像下面这样实现,但我受限于C++20。
auto split = std::views::split(words, ' ');
auto first = split | std::views::take(n);
auto tail = split | std::views::drop(n);
auto ret = std::views::concat(first, tail);
解决方案
你可以先使用 views::take(n) 获取特定分割数量的子串,然后通过访问 views::take(n) 结束迭代器的底层 string_view 迭代器(具备 .base() 成员)来获取剩余的字符串:
auto split = std::views::split(words, ' ');
auto split_n = split | std::views::take(n);
// specific split amount split
for (const auto word : split_n)
std::cout << std::quoted(std::string_view(word.begin(), word.end())) << ' ';
// remaining
const auto rest = std::string_view(
std::ranges::next(split_n.begin(), split_n.end()).base().base(),
words.end());
if (!rest.empty())
std::cout << std::quoted(rest);
说明:
words | views::split(' ') 产生由 string_view::iterator-对组成的三个子区间:"Hello"、"C++"、"20!"。如果随后应用 views::take(1),我们将得到一个 take_view,它将只包含第一子区间,即 "Hello"。
在这种情况下,这个 take_view 的末端实际上指向第二个子区间的起点,即 "C++"。通过调用 ranges::next,我们可以得到一个指向 take_view 末端的 take_view::iterator。
第一个 .base() 从这个 take_view::iterator 中提取底层的 split_view::iterator,第二个 .base() 从 split_view::iterator 中提取底层的 string_view::iterator。
因此,我们最终得到一个指向 "C++" 的 string_view::iterator,由这个迭代器与 words.end() 组成的新 string_view 是 "C++ 20!"。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。