You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++编译阶段替换char*字符串中的指定子串?

C++20 constexpr/consteval 编译期字符串替换实现

实现思路

要在编译期完成字符串字面量的子串替换,核心是在编译阶段完成三个步骤:

  • 计算原字符串、待替换子串、新子串的长度,统计原串中匹配待替换子串的总次数,推导最终生成字符串的固定长度
  • 逐位遍历原字符串,普通字符直接拷贝,匹配到待替换子串时跳过原串对应长度,写入新子串内容
  • 返回固定长度的字符数组包装类型,避免返回const char*带来的悬垂指针问题,同时保证编译期可构造

完整实现代码

#include <array>
#include <cstddef>

// 编译期计算C风格字符串长度
constexpr size_t str_len(const char* str) {
    size_t len = 0;
    while (str[len] != '\0') {
        len++;
    }
    return len;
}

// 校验字符串指定位置是否匹配目标子串
constexpr bool match_substr(const char* str, size_t pos, const char* sub, size_t sub_len) {
    for (size_t i = 0; i < sub_len; i++) {
        if (str[pos + i] != sub[i]) {
            return false;
        }
    }
    return true;
}

// 统计原串中待替换子串的匹配总数
constexpr size_t count_match(const char* str, size_t str_len, const char* old_sub, size_t old_len) {
    size_t cnt = 0;
    size_t i = 0;
    while (i <= str_len - old_len) {
        if (match_substr(str, i, old_sub, old_len)) {
            cnt++;
            i += old_len;
        } else {
            i++;
        }
    }
    return cnt;
}

// 核心编译期替换函数,consteval强制逻辑在编译阶段执行
template<size_t OldLen, size_t NewLen>
consteval auto replace_sub_str(const char* str, const char (&old_sub)[OldLen], const char (&new_sub)[NewLen]) {
    // 字符串字面量数组自带末尾'\0',实际子串长度减1
    constexpr size_t old_real_len = OldLen - 1;
    constexpr size_t new_real_len = NewLen - 1;
    const size_t src_len = str_len(str);
    const size_t match_cnt = count_match(str, src_len, old_sub, old_real_len);
    // 计算结果总长度:原长 - 被替换的旧子串总长 + 新子串总长 + 末尾'\0'
    const size_t res_len = src_len - match_cnt * old_real_len + match_cnt * new_real_len + 1;

    std::array<char, res_len> res{};
    size_t write_pos = 0;
    size_t read_pos = 0;
    while (read_pos < src_len) {
        if (read_pos <= src_len - old_real_len && match_substr(str, read_pos, old_sub, old_real_len)) {
            // 匹配到旧子串,写入新子串
            for (size_t i = 0; i < new_real_len; i++) {
                res[write_pos++] = new_sub[i];
            }
            read_pos += old_real_len;
        } else {
            // 未匹配,直接拷贝原字符
            res[write_pos++] = str[read_pos++];
        }
    }
    res[write_pos] = '\0';
    return res;
}

// 日志宏,固定将子串"XX"替换为"KK",匹配需求示例
#define LOG(x) replace_sub_str(x, "XX", "KK")

使用说明

  • 该实现依赖C++20及以上标准,consteval修饰保证替换逻辑100%在编译阶段执行,无任何运行时开销
  • 调用LOG("hello XX, XX")时,编译期会直接生成内容为"hello KK, KK"的字符数组,可通过.data()方法拿到C风格const char*指针,适配常规日志接口
  • 可通过如下编译期断言校验结果正确性,断言不通过则编译失败:
constexpr auto test_result = LOG("hello XX, XX");
static_assert(test_result[6] == 'K' && test_result[7] == 'K');
static_assert(test_result[10] == 'K' && test_result[11] == 'K');
  • 如果需要替换其他子串,直接修改LOG宏中传入的第二、第三个字符串字面量参数即可,无需修改核心替换逻辑

内容的提问来源于stack exchange,提问作者shoujiang ma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:54:17