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-&gt;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++ - 分割绝对文件路径的主要内容,如果未能解决你的问题,请参考以下文章

绝对路径以及相对路径中的斜杠和反斜杠

C++ WinAPI:处理长文件路径/名称

UWP程序Assets文件夹在运行时的绝对路径怎么表示

xpath路径表达式

C#怎样获取项目的debug路径

C++ Windows - 通过可执行文件路径获取进程的 PID