在C ++中使用两个分隔符拆分字符串

时间:2015-05-16 19:05:14

标签: c++ string

我有一个文件cities.txt,其中包含:

Hayward - San Lorenzo
San Lorenzo - Oakland
Dublin - San Jose
San Mateo - Hayward
San Francisco - Daly City
San Mateo - Oakland
San Francisco - Oakland
Freemont - Hayward
San Lorenzo - Dublin
San Jose - San Mateo
Daly City - San Raphael

我用以下内容阅读了该文件的比赛:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>



int main( ) {
    std::ifstream infile( "cities.txt" ) ;
    if ( infile ) {
        std::string fileData( ( std::istreambuf_iterator<char> ( infile ) ) ,
        std::istreambuf_iterator<char> ( ) ) ;
        infile.close( );
        std::cout << fileData <<"\n\n";
        return 0 ;
   }
   else {
      std::cout << "Where is cities.txt?\n" ;
      return 1 ;
   }
}

并将内容保存在fileData字符串中。我需要将该字符串分解为仅包含城市名称的字符串列表。像这样:

list = {"Hayward","San Lorenzo", "San Lorenzo", "Oakland"......}

我打算将字符串转换成char *并使用strtok,但似乎lika做了很多工作,可以使用标准的字符串函数来完成。 有没有办法做到既快又简洁?

4 个答案:

答案 0 :(得分:2)

我可能会使用std::getline,指定-作为元素之间的分隔符:

std::string city;
while (std::getline(i, city, '-'))
    cities.push_back(city);

一个小细节:这将使白色空间保持不变,因此如果前导和/或尾随空白是一个问题,则必须单独修剪它。

答案 1 :(得分:2)

您可以通过几个步骤完成此操作。

  1. 将文件的内容拆分为字符串向量 - 因此,向量的每个元素都将包含文件的单行

  2. 将文件的每一行拆分为两个元素(行中的两个城市)

  3. 修剪内容

  4. 分割功能可以像这样实现:

    vector<string> split (string str, string seq) { 
        vector<string> ret {};
        size_t pos {};
    
        while ((pos = str.find (seq)) != string::npos) { 
            ret.push_back (str.substr (0, pos));
            str = str.substr (pos+seq.size ()); 
        }
        ret.push_back (str);
    
        return ret;
    }
    

    修剪功能可以这样实现:

    string ltrim (string s) { 
        s.erase (s.begin (), find_if (s.begin (), s.end (), not1 (ptr_fun<int, int> (isspace))));
        return s;
    }
    
    string rtrim (string s) { 
        s.erase (find_if (s.rbegin (), s.rend (), not1 (ptr_fun<int, int> (isspace))).base (), s.end ());
        return s;
    }
    
    string trim (string s) { 
        return ltrim (rtrim (s));
    }
    

    所以,基本上你已经拥有了所有你需要的东西,让我们准备一个结果功能。

    vector<string> result (vector<string>&& content) {
        vector<string> ret {};
        for (const auto& c : content) { 
            auto vec = split (c, "-"); // (2)
            for (const auto& v : vec) { 
                ret.push_back (trim (v));
            }
    
        }
        return ret;
    }
    
    void show (const vector<string>& vec) { 
        for (const auto& v : vec) { 
            cout << "|" << v << "|" << endl;
        }
    }
    

    并且使用情况如下所示,假设您的文件内容位于内容对象中。

    auto vec = result (split (content, "\n")); // (1)
    show (vec);
    

    现在,需要一些解释。让我们看一下(1)我们获取文件的整个内容(我错过了从文件中检索内容)并创建了一个字符串向量,在这种情况下它是行的向量(来自该文件,因为 seq uence是“\ n”)。所以,我们从文件传递给行的结果函数向量。好的,简单,让我们继续吧。现在我们必须将此行拆分为两个字符串(城市)(2),但我们的 seq uence现在是“ - ”。此(2)调用将生成字符串向量,其中包含城市名称。现在,我们所要做的就是将这些名称添加到将返回的向量 ret ,但首先修剪内容以使左右两侧的所有空格都消失。

    结果是:

    |Hayward|
    |San Lorenzo|
    |San Lorenzo|
    |Oakland|
    |Dublin|
    |San Jose|
    |San Mateo|
    |Hayward|
    |San Francisco|
    |Daly City|
    |San Mateo|
    |Oakland|
    |San Francisco|
    |Oakland|
    |Freemont|
    |Hayward|
    |San Lorenzo|
    |Dublin|
    |San Jose|
    |San Mateo|
    |Daly City|
    |San Raphael|
    

答案 2 :(得分:1)

您可以使用string :: find,string :: erase和string :: substr

使用类似的while循环 found = input.find("-"); while(found != string::npos){... }

在城市名称的子区域中,然后用.erase(位置,长度)从整个字符串中删除城市

答案 3 :(得分:1)

您可以使用boost regex_split。我已修改您的代码以演示相同的内容。贴在下面:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <boost/regex.hpp>
#include <vector>



int main( ) {
    std::ifstream infile( "cities.txt" ) ;
    if ( infile ) {
        std::string fileData( ( std::istreambuf_iterator<char> ( infile ) ) ,
        std::istreambuf_iterator<char> ( ) ) ;
        infile.close( );
        std::cout << fileData <<"\n\n";
        std::vector<std::string> out;

        // Delimeter regular expression
        boost::regex delims("\\s+-\\s+|\n|\r");

        boost::regex_split(std::back_inserter(out), fileData, delims);
        for (auto &city : out) {
            std::cout << city << std::endl;
        }
   }
   else {
      std::cout << "Where is cities.txt?\n" ;
      return 1 ;
   }
}