根据 `\n` 处的字符组合/拆分字符串

Split string according to character-combination/ at `\n`

在特定字符组合处将如下所示的字符串拆分为字符串向量的正确方法是什么?

string myString = "This is \n a test. Let's go on. \n Yeah.";

"\n" 拆分得到这个结果:

vector<string> myVector = { 
                              "This is ",
                              " a test. Let's go on. ",
                              " Yeah." 
                           }

我之前使用的是 boost algorithm 库,但现在我想在不使用像 boost 这样的外部库的情况下实现这一切。

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp> 

std::vector<std::string> result;
boost::split(result, "This is \n a test. Let's go on. \n Yeah.", 
              boost::is_any_of("\n"), boost::token_compress_on);

Solution 1: Just to remove "\n" from the string.

只需删除 "\n",您可以使用 erase-remove idiom . SEE LIVE HERE

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
   std::string myString = "This is \n a test. Let's go on. \n Yeah.";
   myString.erase(std::remove(myString.begin(), myString.end(), '\n'), 
                                                      myString.end());
   std::cout << myString<< std::endl;
}

输出:

This is  a test. Let's go on.  Yeah

Solution 2: To remove "\n" from the string and save each split at \n to a vector. (un-efficient)

将所有出现的\n替换为字符串中不存在的其他一些字符(这里我选择了;)。然后借助 std::stringstreamstd::getline 解析如下。 SEE LIVE HERE

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <sstream>

int main()
{
   std::string myString = "This is \n a test. Let's go on. \n Yeah.";
   std::replace(myString.begin(), myString.end(), '\n', ';');
   std::stringstream ssMyString(myString);
   std::string each_split;
   std::vector<std::string> vec;
   while(std::getline(ssMyString, each_split, ';')) vec.emplace_back(each_split);
   for(const auto& it: vec) std::cout << it << "\n";
}

输出:

This is 
 a test. Let's go on. 
 Yeah.

Solution 3: To remove "\n" from the string and save each split at \n to a vector.

遍历字符串并找到 \n(结束位置)找到的位置(使用 std::string::find)。使用起始位置信息和起始位置与结束位置之间的字符数推回子字符串 (std::string::substr)。每次更新开始和结束位置,这样就不会从输入字符串的开头重新开始查找。 SEE LIVE HERE

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstddef>

int main()
{
    std::string myString = "This is \n a test. Let's go on. \n Yeah.";
    std::vector<std::string> vec;

    std::size_t start_pos = 0;
    std::size_t end_pos = 0;
    while ((end_pos = myString.find("\n", end_pos)) != std::string::npos)
    {
        vec.emplace_back(myString.substr(start_pos, end_pos - start_pos));
        start_pos = end_pos + 1;
        end_pos += 2;
    }
    vec.emplace_back(myString.substr(start_pos, myString.size() - start_pos)); // last substring

    for(const auto& it: vec) std::cout << it << "\n";
}

输出:

This is 
 a test. Let's go on. 
 Yeah.

这样的事情怎么样:

#include <iostream> 
#include <sstream>
#include <vector>
#include <string>
#include <iterator>

class line : public std::string {};

std::istream &operator>>(std::istream &iss, line &line)
{
    std::getline(iss, line, '\n');
    return iss;
}

int main()
{

    std::istringstream iss("This is \n a test. Let's go on. \n Yeah.");
    std::vector<std::string> v(std::istream_iterator<line>{iss}, std::istream_iterator<line>{});

    // test
    for (auto const &s : v)
        std::cout << s << std::endl;

    return 0;
}

基本上创建一种新类型的字符串,它是行并使用流迭代器直接读取整行到向量范围构造函数

工作演示:https://ideone.com/4qdfY2