Search code examples
c++pathrelative-path

What is the actual path in C++ and how do I get the relative path?


Hey guys I am starting to learn C++, and there is one thing I do not understand - what is my actual path?

So, for example, in Python, the actual path of xyz.py is where I run python3 xyz.py. But, how does it work in C++?

My C++ project looks like this:

--build
--data
  --exampleData
--src
  --example1
    --include
    --src
      -FileToRun.cc

I build my project "example1" to the build directory. In my project, I want to open the exampleData, what is the relative path for it? Is it relative to the position of FileToRun.cc? Or is it dependentt on how I execute it, like in Python? Or something else?


Solution

  • A relative path is relative to the calling process's current working directory, wherever that happens to be pointing at the moment it is used. The working directory can be specified by a parent process. Or change dynamically during the current process's lifetime. So you can't really rely on the working directory being where you expect at any given moment.

    Your C++ app's default working directory may be your build folder, depending on your configuration, but it will certainly not be your src folder, unless you explicitly set it up that way (for instance, by opening a terminal to the src folder and then running the executable without changing folders. Or creating a shortcut to the executable and setting the working directory in the shortcut's properties).

    This works the same in Python and C++, and any other language, as it is a feature of the OS, not the app.

    If you want to ensure that your relative paths are relative to your executable (or any other root), then you should convert them to absolute paths at runtime. Retrieve your executable's absolute folder path (such as with GetModuleFileName() on Windows, or argv[0] in main(), etc, then strip off the executable's filename), or whatever absolute root you want. Then append your relative path. And then resolve any remaining ./.. as needed.

    So, for example, if you have <path>/build/example1.exe and want to access <path>/data/exampleData, then you would

    • start with <path>/build/example1.exe
    • strip off the filename to get <path>/build/
    • append ../data/exampleData to get <path>/build/../data/exampleData
    • resolve /build/../data/ to /data/
    • thus leaving you with <path>/data/exampleData

    There are APIs to help with this task. Such as PathRemoveFileSpec() and PathCombine()/PathAppend()/PathCanonicalize() on Windows. Or the <filesystem> library in C++17.