如何用std::accumulate拼接Boost::xpressive regex_search匹配结果
嘿,我懂你想摆脱普通for循环,用更函数式的方式来拼接Boost xpressive匹配到的子捕获组——其实std::accumulate完全能搞定,只是之前可能没找对正确的写法~下面就给你详细拆解两种场景的实现方式:
用
std::accumulate拼接子匹配结果 首先要明确:smatch里的what[0]是整个正则匹配的内容,what[1]到what[n]才是你要的子捕获组,所以我们的遍历范围是what.begin()+1到what.end()。
1. 无分隔符的直接拼接
这种情况最简单,直接用空字符串作为初始值,通过lambda把每个子匹配的字符串追加到累计结果里:
std::string result = std::accumulate( what.begin() + 1, what.end(), std::string{}, // 初始值必须是std::string类型,别传const char*的"" [](const std::string& acc, const boost::xpressive::ssub_match& sub) { return acc + sub.str(); } );
2. 带分隔符的拼接(比如添加"-")
直接用accumulate会导致开头/结尾多一个分隔符,这里给你两种优雅的解决方法:
方法一:先拿第一个子串当初始值,再拼接剩余部分
先判断是否存在子捕获组,然后把第一个子串作为初始值,从第二个子串开始累加,每次先加分隔符再加子串:
if (what.size() <= 1) { return ""; // 没有子捕获组的边界情况 } std::string result = std::accumulate( what.begin() + 2, what.end(), what[1].str(), // 用第一个子串当初始值 [](const std::string& acc, const boost::xpressive::ssub_match& sub) { return acc + "-" + sub.str(); } );
方法二:用带状态的lambda处理首尾
如果不想单独处理第一个元素,可以捕获一个布尔变量标记是否是第一次拼接:
bool is_first = true; std::string result = std::accumulate( what.begin() + 1, what.end(), std::string{}, [&is_first](std::string acc, const boost::xpressive::ssub_match& sub) { if (is_first) { is_first = false; acc = sub.str(); } else { acc += "-" + sub.str(); } return acc; } );
完整整合到你的foo函数
把上面的逻辑套进你的代码里,示例如下:
#include <string> #include <numeric> #include <boost/xpressive/xpressive.hpp> std::string foo(const std::string& text) { using namespace boost::xpressive; sregex srx = +_d >> as_xpr("_") >> +_d; // 匹配类似"123_456"的数字组格式 smatch what; if (regex_search(text, what, srx)) { // 这里用带分隔符的方法一示例 if (what.size() <= 1) { return {}; } return std::accumulate( what.begin() + 2, what.end(), what[1].str(), [](const std::string& acc, const ssub_match& sub) { return acc + "-" + sub.str(); } ); } return std::string(); }
比如输入"123_456",会返回"123-456";如果换成无分隔符的代码,会返回"123456"。
为什么之前用std::accumulate失败?
大概率是初始值类型不对——如果你传的是""(const char*类型),accumulate会默认把结果当成const char*处理,拼接时就会出错。一定要明确初始值是std::string{}或者what[1].str()这类std::string类型。
内容的提问来源于stack exchange,提问作者Eugene Mart
相关产品推荐
相关产品推荐

