如何获得当前目录?

Iva*_*nov 53 c++ windows

我一直在C#和Delphi中这样做,但C++是邪恶的.目的是在当前目录中创建一个文件(可执行文件正在运行).

我的代码:

LPTSTR NPath = NULL;
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);
HANDLE hNewFile = CreateFile(NPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
Run Code Online (Sandbox Code Playgroud)

我在GetCurrentDirectory()中遇到异常.

请告诉我为什么我得到一个例外,如何在C++中更容易?

小智 116

我建议您在进一步学习之前阅读一本关于C++的书,因为这样做有助于获得更稳固的基础.Koenig和Moo的加速C++非常出色.

要获取可执行文件路径,请使用GetModuleFileName:

char buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );
Run Code Online (Sandbox Code Playgroud)

这是一个C++函数,它获取没有文件名的目录:

#include <windows.h>
#include <string>
#include <iostream>
using namespace std;;

string ExePath() {
    char buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    string::size_type pos = string( buffer ).find_last_of( "\\/" );
    return string( buffer ).substr( 0, pos);
}

int main() {
    cout << "my directory is " << ExePath() << "\n";
}
Run Code Online (Sandbox Code Playgroud)

  • 注意您可能需要使用宽字符,例如wchar_t buffer [MAX_PATH]; 这些日子... (4认同)
  • 或者`GetModuleFileNameA` (2认同)
  • 重申@Mikhail 所说的内容,您将使用`GetModuleFileNameA` 作为使用多字节字符集的代码,并使用`GetModuleFileNameW` 作为unicode。`GetModuleFileName`(没有 `A` 或 `W`)实际上是你的项目设置使用的任何字符集的别名,这是大多数使用字符串的 Win32 API 方法的设置方式。因此,如果您有一个 unicode 项目,并且您的字符串也是 unicode,那么您只需调用 `GetModuleFileName`。如果您的项目是多字节并使用多字节字符串,则同样适用。 (2认同)
  • 这仅适用于 Windows (2认同)

ava*_*kar 38

GetCurrentDirectory 没有为结果分配空间,这取决于你做到这一点.

TCHAR NPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, NPath);
Run Code Online (Sandbox Code Playgroud)

另外,如果您想以C++方式执行此操作,请查看Boost.Filesystem库.

  • 即使在C#和Delphi下,当前目录也与可执行文件的目录不同.也许你可以让你的问题更清楚? (7认同)

cdi*_*ins 11

恕我直言,这是对anon答案的一些改进.

#include <windows.h>
#include <string>
#include <iostream>

std::string GetExeFileName()
{
  char buffer[MAX_PATH];
  GetModuleFileName( NULL, buffer, MAX_PATH );
  return std::string(buffer);
}

std::string GetExePath() 
{
  std::string f = GetExeFileName();
  return f.substr(0, f.find_last_of( "\\/" ));
}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是不同的。您不提供目录路径,而是提供文件的路径,包括文件。 (2认同)

Ras*_*all 9

问题尚不清楚,是需要当前工作目录还是包含可执行文件的目录路径。

大多数答案似乎都回答了后者。

但是对于前者和创建文件问题的第二部分,C ++ 17标准现在合并了文件系统库,这大大简化了这一过程:

#include <filesystem>
#include <iostream>

std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt";
std::ofstream file(cwd.string());
file.close();
Run Code Online (Sandbox Code Playgroud)

这将获取当前工作目录,将文件名添加到路径并创建一个空文件。请注意,路径对象负责os依赖的路径处理,因此cwd.string()返回os依赖的路径字符串。Neato。


小智 9

一个简单的方法是:

int main(int argc, char * argv[]){
    std::cout << argv[0]; 
    std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)

argv[]几乎是一个包含您运行 .exe 所用参数的数组,但第一个始终是可执行文件的路径。如果我构建它,控制台会显示: C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe

  • 简单的最佳答案。 (2认同)
  • 注意:这不会在程序运行时更新,因此它仅告诉程序从何处运行,不一定是当前工作目录。 (2认同)

MsL*_*ate 7

#include <iostream>    
#include <stdio.h>
#include <dirent.h>

std::string current_working_directory()
{
    char* cwd = _getcwd( 0, 0 ) ; // **** microsoft specific ****
    std::string working_directory(cwd) ;
    std::free(cwd) ;
    return working_directory ;
}

int main(){
    std::cout << "i am now in " << current_working_directory() << endl;
}
Run Code Online (Sandbox Code Playgroud)

我未能正确使用 GetModuleFileName。我发现这项工作非常好。刚刚在 Windows 上测试过,还没有在 Linux 上尝试过:)


小智 6

请不要忘记在使用缓冲区之前将其初始化。同样重要的是,为字符串缓冲区提供结尾 null 的空间

TCHAR path[MAX_PATH+1] = L"";
DWORD len = GetCurrentDirectory(MAX_PATH, path);
Run Code Online (Sandbox Code Playgroud)

参考


Zhi*_*ang 5

WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
Run Code Online (Sandbox Code Playgroud)