带末尾斜杠与不带斜杠的路径调用parent_path结果不同,此行为是否合规?
std::filesystem::path parent_path() 行为疑问
问题场景
假设路径/tmp/test/t的父路径应为/tmp/test,带尾部斜杠的/tmp/test/t/预期父路径也为/tmp/test,但使用C17的std::filesystem::path调用parent_path()时,两者结果不一致:前者返回/tmp/test,后者返回/tmp/test/t,导致断言失败。编译环境为Ubuntu 22.04下的g 11.4.0,编译命令为g++ -std=c++17 main.cpp -o main。
代码示例:
#include <filesystem> #include <iostream> #include <string> #include <cassert> int main(void) { auto parent_one = std::filesystem::path("/tmp/test/t/").parent_path(); auto parent_two = std::filesystem::path("/tmp/test/t").parent_path(); std::cout << parent_one << "\n"; std::cout << parent_two << "\n"; assert(parent_one == parent_two); }
解答
这是符合C++标准规定的正确行为,原因在于std::filesystem::path对路径的解析规则:
- 带尾部斜杠的路径(如
/tmp/test/t/)会被解析为包含一个末尾空元素的路径结构(斜杠作为分隔符,尾部斜杠相当于在最后添加了一个空元素); parent_path()的作用是移除路径结构中的最后一个元素,因此对于带尾部斜杠的路径,移除末尾的空元素后,得到的是/tmp/test/t;而不带尾部斜杠的/tmp/test/t,最后一个元素是t,移除后得到/tmp/test。
如果需要让两种格式的路径返回一致的父路径,可以先调用lexically_normal()标准化路径,该函数会自动移除尾部冗余的斜杠(以及其他冗余路径部分如./、../),示例修改如下:
#include <filesystem> #include <iostream> #include <string> #include <cassert> int main(void) { auto path1 = std::filesystem::path("/tmp/test/t/").lexically_normal(); auto parent_one = path1.parent_path(); auto path2 = std::filesystem::path("/tmp/test/t").lexically_normal(); auto parent_two = path2.parent_path(); std::cout << parent_one << "\n"; std::cout << parent_two << "\n"; assert(parent_one == parent_two); // 此时断言会通过 }
内容的提问来源于stack exchange,提问作者Lars Kakavandi-Nielsen
相关产品推荐
相关产品推荐

