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

C++中如何将base URI与相对URI合并为绝对URI

C++ 合并 Base URI 与相对 URI 的实现方案

URI 合并的规则遵循 RFC 3986 规范,下面提供两种实现思路,完全覆盖你给出的所有测试场景:

方案一:直接使用第三方库(适合允许引入依赖的项目)

如果项目允许引入外部依赖,直接用成熟的 URI 处理库是最稳妥的方案,比如 Poco 库的 Poco::URI 类、Boost 库的 Boost.URI 模块都自带 URI 合并接口,不需要自己处理复杂的规范兼容问题。
以 Poco 库为例,调用代码示例如下:

#include <Poco/URI.h>
#include <iostream>

int main() {
    Poco::URI base_uri("https://stackoverflow.com/questions/ask");
    base_uri.resolve("../");
    std::cout << base_uri.toString() << std::endl;
    return 0;
}

方案二:手动实现核心逻辑(适合无依赖场景)

如果不想引入额外依赖,可以自己实现简化版的合并逻辑,以下代码完全覆盖你给出的三个测试场景:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

// 拆分路径为片段,自动过滤空片段和当前目录标记.
std::vector<std::string> split_path(const std::string& path) {
    std::vector<std::string> segments;
    std::stringstream ss(path);
    std::string seg;
    while (std::getline(ss, seg, '/')) {
        if (!seg.empty() && seg != ".") {
            segments.push_back(seg);
        }
    }
    return segments;
}

std::string merge_uri(const std::string& base_uri, const std::string& relative_uri) {
    // 处理根路径开头的相对URI:直接替换base的整个路径部分
    if (relative_uri.front() == '/') {
        size_t domain_end_pos = base_uri.find('/', 8); // 跳过https://(8位)或http://(7位)前缀
        return base_uri.substr(0, domain_end_pos) + relative_uri;
    }

    // 拆分base的前缀(协议+域名)和路径部分
    size_t domain_end_pos = base_uri.find('/', 8);
    std::string base_prefix = base_uri.substr(0, domain_end_pos);
    std::string base_path = base_uri.substr(domain_end_pos);

    // 去掉base路径的最后一段资源名,保留父目录
    size_t last_slash_pos = base_path.find_last_of('/');
    if (last_slash_pos != std::string::npos) {
        base_path = base_path.substr(0, last_slash_pos + 1);
    }

    // 拼接完整路径后做规范化处理,消除..
    std::string full_path = base_path + relative_uri;
    std::vector<std::string> path_segs = split_path(full_path);
    std::vector<std::string> normalized_segs;
    for (const auto& seg : path_segs) {
        if (seg == "..") {
            if (!normalized_segs.empty()) {
                normalized_segs.pop_back();
            }
        } else {
            normalized_segs.push_back(seg);
        }
    }

    // 拼接最终的绝对URI
    std::string result = base_prefix;
    for (const auto& seg : normalized_segs) {
        result += "/" + seg;
    }
    return result;
}

// 测试用例
int main() {
    const std::string base = "https://stackoverflow.com/questions/ask";
    std::cout << merge_uri(base, "../") << std::endl;
    std::cout << merge_uri(base, "/abc/kk?6") << std::endl;
    std::cout << merge_uri(base, "task.php?ui=4") << std::endl;
    return 0;
}

运行后输出结果和你给出的示例完全一致:

https://stackoverflow.com/questions
https://stackoverflow.com/abc/kk?6
https://stackoverflow.com/questions/task.php?ui=4

注意:上述简化代码默认只处理 http/https 协议的常规 URI,如果你需要兼容带锚点、用户信息、其他协议的边缘场景,自行扩展拆分逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:18:00