使用C++ 11拆分字符串

Mar*_*ark 51 c++ string split c++11

使用c ++ 11拆分字符串最简单的方法是什么?

我已经看过这篇文章所使用的方法,但我觉得使用新标准应该采用一种不那么冗长的方式.

编辑:我希望得到一个vector<string>结果,并能够划分单个字符.

Joh*_*esD 59

std::regex_token_iterator基于正则表达式执行通用标记化.对单个字符进行简单拆分可能有点过分或者可能不过分,但它有效并且不太冗长:

std::vector<std::string> split(const string& input, const string& regex) {
    // passing -1 as the submatch index parameter performs splitting
    std::regex re(regex);
    std::sregex_token_iterator
        first{input.begin(), input.end(), re, -1},
        last;
    return {first, last};
}
Run Code Online (Sandbox Code Playgroud)

  • [`regex_token_iterator`](http://en.cppreference.com/w/cpp/regex/regex_token_iterator)在C++ 11中定义,但GCC在版本4.9之前不支持它(参见[here](http) ://stackoverflow.com/a/8913707/86967na)).使用早期版本的GCC,您可以使用[Boost regex](http://www.boost.org/doc/libs/release/libs/regex/). (13认同)
  • 应该提到这是MSFT特有的.在POSIX系统上不存在. (2认同)
  • 对于空白来说,一个好的正则表达式将是`\\ s +`.另外,在gcc 4.9上,我必须在将其传递给迭代器构造函数之前使用string参数显式初始化正则表达式.只需添加`regex re {regex_str};`作为第一行,其中`regex_str`是示例中名为`regex`的字符串,然后传递`re`. (2认同)

Yag*_*ang 21

这是一种(可能不那么冗长)分割字符串的方式(基于你提到的帖子).

#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> split(const std::string &s, char delim) {
  std::stringstream ss(s);
  std::string item;
  std::vector<std::string> elems;
  while (std::getline(ss, item, delim)) {
    elems.push_back(item);
    // elems.push_back(std::move(item)); // if C++11 (based on comment from @mchiasson)
  }
  return elems;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用的是C++ 11,那么在插入向量时也可以这样做以避免字符串副本:elems.push_back(std :: move(item)); (8认同)
  • 即使“item”是在堆栈上定义的,内部数据指针也指向堆上分配的数据。通过使用“std::move”,将选择“push_back(std::string&amp;&amp;)”重载,从而导致向量内的“std::string”对象通过 move 进行初始化——只需复制数据指针,而不是而不是复制整个缓冲区。 (3认同)

fdu*_*uff 12

这是一个分割字符串并使用提取的元素填充向量的示例boost.

#include <boost/algorithm/string.hpp>

std::string my_input("A,B,EE");
std::vector<std::string> results;

boost::algorithm::split(results, my_input, is_any_of(","));

assert(results[0] == "A");
assert(results[1] == "B");
assert(results[2] == "EE");
Run Code Online (Sandbox Code Playgroud)


wal*_*lly 8

另一个正则表达式解决方案受到其他答案的启发,但希望更短更容易阅读:

std::string s{"String to split here, and here, and here,..."};
std::regex regex{R"([\s,]+)"}; // split on space and comma
std::sregex_token_iterator it{s.begin(), s.end(), regex, -1};
std::vector<std::string> words{it, {}};
Run Code Online (Sandbox Code Playgroud)

  • 在这里找到答案:[空花括号作为范围结束](/sf/ask/2108688571/) (2认同)
  • 如果其他人想知道:“sregex_token_iterator”构造函数的“-1”参数会导致对象迭代匹配的片段。默认值“0”将迭代与正则表达式匹配的片段。有关更多详细信息,请参阅[此处](https://en.cppreference.com/w/cpp/regex/regex_token_iterator)。 (2认同)

Fai*_*ali 5

我不知道这是否不那么冗长,但对于那些在动态语言(例如 javascript)方面经验丰富的人来说,可能更容易理解。它使用的唯一 C++11 特性是 lambdas。

#include <string>
#include <cctype>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  string s = "hello  how    are you won't you tell me your name";
  vector<string> tokens;
  string token;

  for (const auto& c: s) {
    if (!isspace(c))
      token += c;
    else {
      if (token.length()) tokens.push_back(token);
      token.clear();
    }
  }

  if (token.length()) tokens.push_back(token);
     
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不`for (auto const c : s) {...}`? (15认同)