C++11及以上如何将函数作为regex_replace()的第三个参数?
解决C++ regex_replace编译错误并修复异常JSON字符串
编译错误原因
std::regex_replace接受自定义替换逻辑时,对可调用对象的签名有严格要求,直接传replace函数名会让编译器无法匹配正确的重载版本——因为regex_replace有多个重载,函数指针类型不匹配。- 你的
replace函数参数是std::smatch,但regex_replace要求的替换回调签名应为std::string(const std::sub_match<std::string::iterator>&),或者用std::function包装适配。
修复步骤与完整代码
1. 修正替换逻辑的签名
可以调整函数签名符合要求,或者用lambda表达式(更简洁,编译器能自动推导类型)。
2. 优化正则表达式
原正则\\:\s*\"(.*)\"是贪婪匹配,会错误捕获超出值范围的内容,且未处理未转义的双引号,需要调整正则精准匹配异常的JSON值部分。
3. 避免错误分割JSON
原代码用逗号分割JSON会有问题(比如字符串里包含逗号时会拆错),直接对整个字符串处理更可靠。
完整可运行代码:
#include <iostream> #include <string> #include <regex> #include <functional> int main(){ // 原始异常JSON字符串 std::string str = R"({"key":"v\"a\"lue","key2":"v"a"lue2"})"; // 匹配键值对中的值部分,捕获未正确转义的内容 std::regex pattern(R"(:\s*"([^"]*(?<!\\)"[^"]*)*")"); // 使用lambda作为替换器,直接修复未转义的双引号 std::string fixedJson = std::regex_replace(str, pattern, [](const std::smatch& match) { // 获取键的部分(比如"key":) std::string keyPrefix = match.prefix().str(); // 获取值的原始内容 std::string rawValue = match[1].str(); // 替换所有未被转义的双引号 std::regex unescapedQuote(R"((?<!\\)")"); std::string escapedValue = std::regex_replace(rawValue, unescapedQuote, "\\\""); // 拼接成合法的键值对部分 return keyPrefix + "\"" + escapedValue + "\""; }); std::cout << "修复后的JSON:" << std::endl; std::cout << fixedJson << std::endl; return 0; }
代码说明
- lambda替换器:lambda的参数是
const std::smatch&,完全符合regex_replace的要求,编译器能正确识别,不会再出现重载匹配错误。 - 正则匹配逻辑:
:\s*"([^"]*(?<!\\)"[^"]*)*"专门匹配JSON键值对中的值部分,能捕获包含未转义双引号的内容。 - 异常修复:用
(?<!\\)"匹配所有没有被反斜杠转义的双引号,替换成\",让整个JSON字符串合法。
编译错误的快速修复(保留独立函数)
如果一定要用独立函数,需要用std::function包装适配类型:
#include <iostream> #include <string> #include <regex> #include <functional> std::string fixValue(const std::smatch& match) { std::string keyPrefix = match.prefix().str(); std::string rawValue = match[1].str(); std::regex unescapedQuote(R"((?<!\\)")"); std::string escapedValue = std::regex_replace(rawValue, unescapedQuote, "\\\""); return keyPrefix + "\"" + escapedValue + "\""; } int main(){ std::string str = R"({"key":"v\"a\"lue","key2":"v"a"lue2"})"; std::regex pattern(R"(:\s*"([^"]*(?<!\\)"[^"]*)*")"); // 用std::function包装函数,让类型匹配regex_replace的要求 std::function<std::string(const std::smatch&)> replacer = fixValue; std::string fixedJson = std::regex_replace(str, pattern, replacer); std::cout << fixedJson << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

