c++ - 分割绝对文件路径
Posted
技术标签:
【中文标题】c++ - 分割绝对文件路径【英文标题】:c++ - Splitting an absolute file path 【发布时间】:2016-06-02 11:44:37 【问题描述】:我正在为学校作业编写 C++ 程序。在某些时候,这个问题需要我更改目录,我知道该怎么做。但是,用户将向程序提供文件的绝对路径。我想要做的是将目录更改为该文件所在的位置。例如,如果我在目录 dir2 中,并且用户想要转到该文件
/home/dir1/dir2/dir3/dir4/file
我想做
int ret = chdir("home/dir1/dir2/dir3/dir4");
我的问题是如何将用户给定的字符串拆分成
/home/dir1/dir2/dir3/dir4/
和
file
编辑我想通了。我首先将绝对路径名从 const char* 转换为字符串。然后我使用 .find_last_of("/") 字符串成员来查找字符串中最后一个“/”的位置。然后我使用 .substr() 成员获取从 0 到 .find_last_of 返回的位置的子字符串
【问题讨论】:
把你的橡皮鸭——en.wikipedia.org/wiki/Rubber_duck_debugging——放在你的键盘旁边,用简单的英语向你的橡皮鸭解释你的逻辑,一步一步的算法。一旦你的橡皮鸭同意你的算法可以工作,只需接受你的解释,并将其翻译成代码。 我不太确定以这种方式拆分字符串的选项。我知道我可以使用字符串流根据空格拆分它。但这是一个不同的分隔符。我想根据最后一个'/'来拆分它 std::string 类具有拆分和切分字符串的方法,以任何您喜欢的方式。如果您想在位置 #n 之前或之后提取部分字符串,std::string 提供了几种方法来执行此操作。 【参考方案1】:只需获取文件路径中“/”字符的最后一个索引,然后从字符串中截取带有扩展名的文件。
1) 检查目录列表是否有“/”。如果不是 - 抛出错误。
2) 获取字符串中“/”的最后一个索引。
3) 返回目录字符串的子字符串,使用函数结果的最后一个索引(一个数字)作为起始索引和目录字符串的总长度。
希望对您有所帮助。
【讨论】:
【参考方案2】:将您的路径放入std::string
,然后您可以执行以下操作。
std::string path = "/home/person/dir/file";
std::size_t botDirPos = path.find_last_of("/");
// get directory
std::string dir = path.substr(0, botDirPos);
// get file
std::string file = path.substr(botDirPos, path.length());
// change directory.
chdir(dir.c_str());
【讨论】:
【参考方案3】:你可以使用
std::string dir_str = "path/file";
auto pos = dir_str.rfind("/");
if (pos!= std::string::npos)
chdir("newpath"+dir_str.substr(pos));
//...
else
//do something;
文件名中可能存在字符 / 等问题。但假设这只是一个为简单测试而设计的玩具程序,它应该可以工作。
如果您有点认真地处理文件(例如递归地遍历目录),我建议您使用类似 boost::file_system 的东西。
【讨论】:
【参考方案4】:您可以使用<string.h>
中的strtok
函数来拆分路径组件,并顺便跟踪层次结构中的每个目录。
#include <stdio.h>
#include <string.h>
int main ()
char str[] ="/path/to/file";
char * pch;
char * temp;
pch = strtok (str,"/");
while ( (temp = strtok (NULL, "/") ) != NULL)
pch = temp;
printf("The file is: %s", pch);
return 0;
【讨论】:
【参考方案5】:为了增加大量答案,我在查找 stat
结构和函数后设计了这个:
struct ab_path
int delimiter = 0;
int extension = 0;
int length = 0;
char separator = '\0';
ab_path()
operator bool()
return (this->delimiter != 0) | (this->extension != 0) | (this->length != 0) | (this->separator != '\0') ;
;
bool ab_path( const char* name , struct ab_path* ap )
while(1)
if(name[ap->length] == '\0')break;
if(name[ap->length] == '.') ap->extension = ap->length;
if(name[ap->length] == '/')
ap->delimiter = ap->length; ap->separator = name[ap->length];
if(name[ap->length] == '\\')
ap->delimiter = ap->length;ap->separator = name[ap->length];
++ap->length;
return (bool)ap;
struct ab_path ap;
bool valid = ap_path("superb.naming.type", &ap );
但是您可以重写 ap->delimiter
以接受某种容器(std::vector
,std::array
...)并存储多个分隔符。
【讨论】:
【参考方案6】:这可能会有所帮助。 它的作用是将文件路径与相应的目录/文件分开,并将名称存储在一个向量中。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
string filePath = "C:\\ProgramData\\Users\\CodeUncode\\Documents";
vector<string> directories;
size_t position=0, currentPosition=0;
while(currentPosition != -1)
currentPosition = filePath.find_first_of('\\', position);
directories.push_back(filePath.substr(position,currentPosition-position));
position = currentPosition+1;
for(vector<string>::iterator it = directories.begin(); it!=directories.end(); it++)
cout<<*it<<endl;
return 0;
【讨论】:
您需要改进您的代码 sn-p:例如,添加所需的标准库头文件。此外,将int
用于应该为size_t
(返回值为find_first_of
)是不好的做法。【参考方案7】:
这个问题的所有其他答案都会找到“/”(Unix)或“\”(Windows),并手动切分字符串;这是冗长的并且受用户错误的影响。 C++17 现在有 std::filesystem
包,它以操作系统友好的方式从路径中干净地提取目录和文件名:
#include <filesystem>
void Test()
std::filesystem::path path("/home/dir1/dir2/dir3/dir4/file");
std::string dir = path.parent_path().string(); // "/home/dir1/dir2/dir3/dir4"
std::string file = path.filename().string(); // "file"
【讨论】:
以上是关于c++ - 分割绝对文件路径的主要内容,如果未能解决你的问题,请参考以下文章