给定两个绝对路径 A 和 B,如何获取从 A 到 B 的相对路径

Given two absolute paths A and B, how to get the relative path from A to B

提问人:saiko 提问时间:7/5/2023 最后编辑:saiko 更新时间:7/6/2023 访问量:97

问:

我有一个程序,它生成一个标头和一个源文件,两者都可以存储在彼此不同的方向上。我想将头文件作为源文件中的包含,这是我的问题,我如何构造包含,即使它们在完全不同的目录中也能正常工作?

例如,source path: , header path: => (include 中没有绝对路径,不使用第三方库)。C:/AA/BB/EE/source.cppC:/AA/CC/DD/header.h#include "../../CC/DD/header.h

我目前的想法是,我在斜杠之间拆分两条路径,将它们放入一个数组中并进行比较,但我无法弄清楚其余的。

C++ 包含路径

评论

0赞 Pepijn Kramer 7/5/2023
std::filesystem 有一些您可以使用的功能。例如 filesystem::relative 和 proximate
0赞 Jabberwocky 7/5/2023
directionarys == 目录
0赞 463035818_is_not_an_ai 7/5/2023
所以你的问题归结为“给定两个绝对路径 A 和 B,如何获得从 A 到 B 的相对路径”,对吧?

答:

3赞 463035818_is_not_an_ai 7/5/2023 #1

您可以使用:std::filesystem::relative

#include <iostream>
#include <filesystem>

int main() {
    auto p = std::filesystem::relative("a/b/c/d","a/b/x/y");
    std::cout << p;
}

输出

"../../c/d"

评论

0赞 saiko 7/5/2023
是的,这将是想要的输出,但是在不使用文件系统的情况下,这样的事情是否可能?
0赞 463035818_is_not_an_ai 7/5/2023
@saiko c++14 没有相对路径 afaikstd::experimental::filesystem
0赞 hennep 7/5/2023 #2

没有文件系统:

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

using namespace std;

template <typename out>
void split( const std::string &s, char delimeter, out result ) {
    std::istringstream iss( s );
    std::string item;
    while( std::getline( iss, item, delimeter ) ) {
        *result++ = item;
    }
}

std::vector<std::string> split( const std::string &s, char delimeter ) {
    std::vector<std::string> elems;
    split( s, delimeter, std::back_inserter( elems ) );
    return elems;
}

int main() {
    string source_file = "C:/AA/BB/EE/source.cpp";
    string header_file = "C:/AA/CC/DD/header.h";
    string include = "";
    string extra = "";
    std::vector<std::string> cpp = split( source_file, '/' );
    std::vector<std::string> hpp = split( header_file, '/' );
    std::vector<std::string>::iterator c = cpp.begin();
    std::vector<std::string>::iterator h = hpp.begin();
    while( *h == *c && *c != *cpp.end()  && *h != *hpp.end() ) {
        h++;
        c++;
    }
    while( *c != *cpp.end() ) {
        if( *c != *cpp.rbegin() ) {
            include += "../";
        }
        c++;
    }
    while( *h != *hpp.end() ) {
        if( *h == *hpp.rbegin() ) {
            include += extra;
            include += *hpp.rbegin();
        } else {
            extra += *h;
            extra += "/";
        }
        h++;
    }
    std::cout << include << endl;
}

但就我个人而言,我更喜欢,+1 for @ 463035818_is_not_an_aistd::filesystem::relative

评论

0赞 saiko 7/6/2023
似乎不起作用,拆分很好,但包含和额外总是空的。
0赞 hennep 7/6/2023
就我而言,它显示:../../CC/DD/header.h 您是否使用了相同的文件名?或者带有反斜杠的东西,在这种情况下,拆分分隔符和所有其他正斜杠都必须是“\\”
0赞 saiko 7/6/2023
好吧,我只是复制了整个东西来尝试一下。
0赞 saiko 7/6/2023
让它工作,问题在于 while 循环需要比较那里的值而不是迭代器。