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
相关产品推荐
相关产品推荐

