【问题标题】:c++ - Splitting an absolute file pathc++ - 分割绝对文件路径
【发布时间】: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 提供了几种方法来执行此操作。

标签: c++ split absolute-path chdir


【解决方案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"
            }
            

            【讨论】:

              猜你喜欢
              • 2011-07-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-06-15
              • 1970-01-01
              • 2012-04-24
              • 2011-01-26
              相关资源
              最近更新 更多