当您并不总是知道确切的路径时,您如何告诉C++使用文件夹中的特定文件?

  • 本文关键字:C++ 何告诉 文件夹 文件 路径 c++
  • 更新时间 :
  • 英文 :


注意:我目前只对C有深入的了解,但我参加了一个暑期课程,很快就会开始学习现代c++,所以c++ 20的方法也会非常有帮助。如果这是一个愚蠢的问题,或者已经有人问过了(我没有从谷歌上找到任何东西),那么链接也会很有帮助。

问题:

好的,假设我在设计一个程序。我想让程序打开一个文件,我可以告诉它确切的路径,或者把它放在我的工作目录中。为了便于示例,让我们在下面创建两条路径:

  • (我的电脑路径)/project/partone/mainfiles/main.c
  • (我电脑路径)/project/parttwo/mainfiles/data.csv

这通常不是问题,因为我可以给main.c提供data.csv的完整路径。但是如果我想发布程序呢?然后下载它的人在他们的计算机上会有一个不同的路径,自动使代码失败。

是否有办法在c++ 20(首选答案)和/或C99(如果你知道C99,至少给我一些关键词谷歌c++ 20,我听说C代码的大部分是可用于c++)。

我在想也许c++ 20中有一些包可以像"cd"命令,它可以从我所在的目录开始更改目录。比如告诉c++(从project/partone/mainfiles):

//pseudocode
cd ..
cd ..
cd parttwo
cd mainfiles
fopen data.csv

下面是一个小的辅助模块,用于获取可创建/可写目录的路径,用于保存程序数据。

appdata_path.hpp

#ifndef APPDATA_PATH_HPP
#define APPDATA_PATH_HPP
#include <filesystem>
#include <string>
std::filesystem::path
get_appdata_path( const std::string & application_name );
#endif

appdata_path.cpp

#include "appdata_path.hpp"
#ifdef _WIN32
#include <windows.h>
#include <shlobj.h>
#include <objbase.h>
#pragma comment(lib,"Shell32")
#pragma comment(lib,"Ole32")
std::filesystem::path
get_known_folder_path( REFKNOWNFOLDERID rfid )
{
wchar_t * p;
if (S_OK != SHGetKnownFolderPath( rfid, 0, NULL, &p )) return "";
std::filesystem::path result = p;
CoTaskMemFree( p );
return result;
}
std::filesystem::path
get_appdata_path( const std::string & application_name )
{
auto path = get_known_folder_path( FOLDERID_LocalAppData );  // or FOLDERID_RoamingAppData
if (!path.empty()) path /= application_name;
return path;
}
#else
#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
std::filesystem::path
get_appdata_path( const std::string & application_name )
{
const char * p = getenv( "HOME" );
if (p) return p + ("/" + application_name);
struct passwd * pw = getpwuid( getuid() );
if (pw) return pw->pw_dir + ("/" + application_name);
return "";
}
#endif

example.cpp

#include <iostream>
#include "appdata_path.hpp"
int main()
{
auto path = get_appdata_path( "Example Application" );
if (path.empty()) std::cout << "Wut?n";
else              std::cout << path << "n";
}

指出:

  • 注意,Windows代码在本地和漫游之间有一个选择。除非你打算让你的应用程序在多台计算机上运行,否则请使用Local。

  • 文件名中某些字符无效(在Windows上)。一般来说,在命名文件时应该避免使用奇怪的字符,所以应该为应用程序使用一个简化的、文件系统友好的名称。正如您在示例中看到的那样,空格是可以的,但是是否使用它们取决于您。

  • 请注意,代码除了返回一个有效路径之外什么都不做。它不创建或验证路径的存在性。你必须自己做这件事。

例如,要保存数据,您可以使用如下命令:

void save_data()
{
auto save_directory = get_appdata_path( "Quuxer" );
auto save_filename = save_directory / "data.csv";
if (save_directory.empty())
std::filesystem::create_directory( save_directory );
std::ofstream f( save_filename );
f << my_data;
}

此模块在Windows上按原样编译MSVC。如果你使用不同的编译器(GCC或LLVM/Clang),你需要显式地链接Shell32.libOle32.lib

它在Linux(和Mac也一样!)上按原样编译。

需要c++ 17,我想。

相关内容

最新更新