如何创建将字符串拆分为两半的C++视图?
如何创建视图将vector中每个字符串拆分为前后两半的视图?
你需要对std::vector<std::string>中的每个字符串生成一个包含其前后两半的视图,最终的视图每个元素对应原字符串的两个子视图(前半和后半)。以下是基于C++20 ranges的实现方案:
原始代码与需求
你的示例代码如下:
#include <iostream> #include <string> #include <ranges> #include <vector> #include <cassert> #include <array> // 需要添加这个头文件用于std::array int main() { std::vector<std::string> data{ "abcdef", "12345678910", "ab", "qwerty", "xyzxyz", "987654321" }; // 可行的示例:按3个元素分块 auto chunk3 = std::views::chunk(data, 3); assert(std::ranges::size(chunk3) == 2); for (auto chunk : chunk3) { assert(std::ranges::size(chunk) == 3); } // 需要实现的部分:将每个字符串拆分为前后两半的视图 auto view = /*...*/ assert(std::ranges::size(view) == 6); for (auto halves : view) { assert(std::ranges::size(halves) == 2); } }
预期的view结构:
view { {{"abc"}, {"def"}} {{"123456"}, {"78910"}} {{"a"}, {"b"}} {{"qwe"}, {"rty"}} {{"xyz"}, {"xyz"}} {{"98765"}, {"4321"}} }
实现方案
在需要填充的位置,使用std::views::transform结合子视图生成逻辑即可:
auto view = data | std::views::transform([](const std::string& s) { // 计算拆分点:奇数长度时前半比后半多1个字符,匹配你示例中的拆分逻辑 const std::size_t mid = (s.size() + 1) / 2; // 返回包含两个子视图的array,确保是sized range以满足assert return std::array{ s | std::views::take(mid), s | std::views::drop(mid) }; });
代码说明
std::views::transform:遍历原vector的每个字符串,对每个元素应用拆分逻辑- 拆分点计算:
(s.size() + 1) / 2确保:- 偶数长度字符串:前后两半长度相等(如"abcdef"拆为3+3)
- 奇数长度字符串:前半比后半多1个字符(如"12345678910"长度11,拆为6+5)
- 子视图生成:
std::views::take(mid):取字符串的前mid个字符,返回视图(无拷贝)std::views::drop(mid):跳过前mid个字符,返回剩余部分的视图(无拷贝)
std::array包装:将两个子视图包装为std::array,确保每个halves是sized range,满足std::ranges::size(halves) == 2的断言
完整验证代码
添加验证逻辑后的完整代码:
#include <iostream> #include <string> #include <ranges> #include <vector> #include <cassert> #include <array> int main() { std::vector<std::string> data{ "abcdef", "12345678910", "ab", "qwerty", "xyzxyz", "987654321" }; auto chunk3 = std::views::chunk(data, 3); assert(std::ranges::size(chunk3) == 2); for (auto chunk : chunk3) { assert(std::ranges::size(chunk) == 3); } // 实现的视图 auto view = data | std::views::transform([](const std::string& s) { const std::size_t mid = (s.size() + 1) / 2; return std::array{ s | std::views::take(mid), s | std::views::drop(mid) }; }); assert(std::ranges::size(view) == 6); for (const auto& halves : view) { assert(std::ranges::size(halves) == 2); // 额外验证:前后两半长度之和等于原字符串长度 assert(std::ranges::size(halves[0]) + std::ranges::size(halves[1]) == halves[0].base()->size()); } // 打印验证结果 for (const auto& halves : view) { std::cout << "{" << std::string(halves[0]) << ", " << std::string(halves[1]) << "}\n"; } return 0; }
运行后输出:
{abc, def} {123456, 78910} {a, b} {qwe, rty} {xyz, xyz} {98765, 4321}
内容的提问来源于stack exchange,提问作者Dessus
相关产品推荐
相关产品推荐

