【问题标题】:C++ argv path specifierC++ argv 路径说明符
【发布时间】:2011-02-06 06:26:22
【问题描述】:

在我的编程语言的解释器中,我必须正确处理这些部分,以防调用 import 函数。然后我需要检查这样的文件是否在/libs 文件夹中(与我的可执行文件位于同一位置!),如果它不存在,我必须检查当前脚本的目录。

  • 如何从 argv 获取可执行文件所在目录的确切路径?
  • 从路径末尾删除文件的最佳方法是什么,例如:

    C:/a/b/c/file.exe 应该变成C:/a/b/c/

【问题讨论】:

    标签: c++ string path argv


    【解决方案1】:
    1. 没有保证可以做到这一点。您可以尝试查看 argv[0],但它是否包含完整路径或仅包含二进制文件的名称取决于平台以及您的进程是如何被调用的。
    2. 您可以使用strrchr 查找最后一个斜线并将其后面的字符替换为'\0'

    代码示例:

    // 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
    }
    

    【讨论】:

      【解决方案2】:

      从字符串末尾向后扫描第一个 '/' 字符。

      【讨论】:

        【解决方案3】:

        如果 argv[0] 不包含整个路径,Linux(可能还有其他 *nix)上的一种不可移植方式是在 /proc/self/exe 上使用 readlink。

        【讨论】:

          【解决方案4】:

          不是最佳的,但工作正常:

          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;
          }
          

          对于相对路径,我使用的是 unix/linux 特定的 realpath()。对于windows你可以使用GetModuleFileName(NULL, buffer, MAXPATHLEN),当然分隔符不一样。

          【讨论】:

            【解决方案5】:

            如果您的环境在环境中具有 PWD 的等价物,您只需将 /$argv[0] 附加到它。

            这可能会给您带来意想不到的东西,例如 /foo1/foo2/../foo3/ 但这没关系。这是一条有效的路径,可以通配。

            【讨论】:

            • 工作目录通常与可执行文件的位置不同。
            • 这是不正确的。 PWD 是您的工作目录。如果程序是通过 PATH 找到的,那么它的位置与工作目录无关。
            • 或者如果它被可执行文件的第一行找到。或者如果程序以除./my_prog 之外的任何方式执行。问题表明这是一个解释器。
            【解决方案6】:

            对于 Windows(非便携式),请使用 ::GetModuleFileName() 和 ::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
            

            【讨论】:

              猜你喜欢
              • 2018-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-06-18
              • 2018-11-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多