开发者

C++ argv path specifier

In the interpreter for my programming languages I have to correctly handle the parts in case the import function is called. I then need to check if such a file is in the /libs folder (loc开发者_如何学Pythonated at the same place as my executeable!) and if it doesn't exist I have to check in the directory of the current script.

  • How can I get the exact path to the directory where the executeable is located from argv?
  • What is the best way to remove the file from the end of a path, e.g:

    C:/a/b/c/file.exe should become C:/a/b/c/


  1. There is no guaranteed way to do that. You can try looking in argv[0] but whether that has the full path or just the name of the binary depends on the platform and how your process was invoked.
  2. You can use strrchr to find the last slash and replace the character after it with '\0'

Code example:

// Duplicate the string so as not to trash the original
// You can skip this if you don't mind modifying the original data
// and the originald is writeable (i.e. no literal strings)
char *path = strdup(...);

char *last_slash = strrchr(path, '/');
if (last_slash)
{
#if PRESERVE_LAST_SLASH
    *(last_slash + 1) = '\0';
#else
    *last_slash = '\0';
#endif
}


A non-portable way on Linux (and maybe other *nix) would be to use readlink on /proc/self/exe if argv[0] doesn't contain the entire path.


If your environment has the equivalent of PWD in the environment, you can just append /$argv[0] to it.

This might give you something you don't expect like /foo1/foo2/../foo3/ but that's ok. It's a valid path and can be globbed.


Scan backwards from the end of a string for the first '/' character.


Not optimal, but works fine:

int main(int argc, char **argv) {
    using namespace std;
    char buffer[MAXPATHLEN];
    realpath(argv[0], buffer);
    string fullpath = buffer;
    fullpath = string(fullpath, 0, fullpath.rfind("/"));
    cout << fullpath << endl;
}

For relative path I'm using realpath(), which is unix/linux specific. For windows you could use GetModuleFileName(NULL, buffer, MAXPATHLEN), and of course the separator isn't the same.


For Windows (non portable) use ::GetModuleFileName() and ::PathRemoveFileSpec():

TCHAR sPath[MAX_PATH] = {0};
if(::GetModuleFileName(NULL, sPath, MAX_PATH))
    ::PathRemoveFileSpec(sPath))
// sPath is the executable path if the module is an exe
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜