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 becomeC:/a/b/c/
- 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. - 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
精彩评论