【C++Note】获取可执行文件所在目录
需求
程序与配置文件放在同一个目录,需要运行程序时加载配置文件
假设:demo.exe
和config.xml
在同一目录,运行demo
程序获得config.xml
绝对路径
有时候程序所在目录不一定就是当前工作目录,因此不能直接使用getcwd
测试环境
- Windows
- Windows 11
- mingw g++ 9.2.0
- Linux
- WSL:Ubuntu-20.04
- g++ 9.4.0
验证
C++17
C++17引入文件系统库(std::filesystem
)
#include <filesystem>
namespace fs = std::filesystem;
fs::path path_xml = fs::canonical(fs::path(argv[0]).parent_path()) / "config.xml";
result = path_xml.string();
Windows
如果编译器不支持或不允许使用C++17,windows下
char path_root[200];
::memset(path_root,0,sizeof(path_root));
char *p = NULL;
std::cout << "System:Windows" << std::endl;
::GetModuleFileNameA(NULL, path_root, 200);
if (NULL != (p = strrchr(path_root, '\\')))
{
*p = '\0';
}
result = std::string(path_root) + "\\config.xml";
Linux
char path_root[200];
::memset(path_root,0,sizeof(path_root));
char *p = NULL;
std::cout << "System:Linux" << std::endl;
::readlink("/proc/self/exe", path_root, 200);
if (NULL != (p = strrchr(path_root, '/')))
{
*p = '\0';
}
result = std::string(path_root) + "/config.xml";
完整程序
#include <iostream>
#include <cstring>
#if __cplusplus >= 201703L
// C++ 17
#include <filesystem>
#else
// __cplusplus < C++17
#ifdef _WIN32
// Windows
#include <Windows.h>
#else
// Linux
#include <unistd.h>
#endif
#endif
int main(int argc, char *argv[])
{
/*
* 目标:获取与本程序同一目录的配置文件的绝对路径
* 假设:demo.exe config.xml 在同一目录,运行demo程序获得config.xml绝对路径
*/
std::cout << "C++ standard:" << __cplusplus << std::endl;
std::string result;
#if __cplusplus >= 201703L
// C++
namespace fs = std::filesystem;
fs::path path_xml = fs::canonical(fs::path(argv[0]).parent_path()) / "config.xml";
result = path_xml.string();
#else
// __cplusplus < C++17
char path_root[200];
::memset(path_root,0,sizeof(path_root));
char *p = NULL;
#ifdef _WIN32
// Windows
std::cout << "System:Windows" << std::endl;
::GetModuleFileNameA(NULL, path_root, 200);
if (NULL != (p = strrchr(path_root, '\\')))
{
*p = '\0';
}
result = std::string(path_root) + "\\config.xml";
#else
// Linux
std::cout << "System:Linux" << std::endl;
::readlink("/proc/self/exe", path_root, 200);
if (NULL != (p = strrchr(path_root, '/')))
{
*p = '\0';
}
result = std::string(path_root) + "/config.xml";
#endif
#endif
std::cout << result << std::endl;
}