C++ 使用多个分隔符拆分字符串并将其保存到向量中

C++ 使用多个分隔符拆分字符串并将其保存到向量中,c++,string,vector,split,delimiter,C++,String,Vector,Split,Delimiter,我知道有很多话题都有我这样的问题,但我找不到正确的答案 我想用多个分隔符(“,”\n“,”(“,)”)将我的字符串拆分为标记,并将所有标记保存在我的向量中(甚至是分隔符) 这是我编写的第一个代码,它实际上只占用所有行,但现在我想用其他分隔符将其拆分 std::vector<std::string> Lexer::getToken(std::string flow) { std::string token; std::vector<std::string>

我知道有很多话题都有我这样的问题,但我找不到正确的答案

我想用多个分隔符(
”\n“
”(“
)”
)将我的字符串拆分为标记,并将所有标记保存在我的向量中(甚至是分隔符)

这是我编写的第一个代码,它实际上只占用所有行,但现在我想用其他分隔符将其拆分

std::vector<std::string> Lexer::getToken(std::string flow)
{
    std::string token;
    std::vector<std::string> tokens;
    std::stringstream f;

    f << flow;
    while (std::getline(f, token, '\n'))
    {
        tokens.push_back(token);
    }
    return (tokens);
}
std::vector Lexer::getToken(std::string flow)
{
字符串标记;
std::向量标记;
std::stringstream f;

f对此,我将使用正则表达式:

#include <regex>

std::vector<std::string> getToken(std::string const &flow) {
  // Delimiter regex. Depending on your desired behavior, you may want to
  // remove the + from it; with the +, it will combine adjacent delimiters
  // into one. That is to say, "foo (\n) bar" will be tokenized into "foo",
  // "bar" instead of "foo", "", "", "", "", "bar".
  std::regex re("[ \n()]+");

  // range-construct result vector from regex_token_iterators
  return std::vector<std::string>(
      std::sregex_token_iterator(flow.begin(), flow.end(), re, -1),
      std::sregex_token_iterator()
    );
}
#包括
std::vector getToken(std::string const&flow){
//分隔符正则表达式。根据所需的行为,您可能需要
//将+从中删除;使用+,它将合并相邻的分隔符
//即“foo(\n)bar”将标记为“foo”,
//用“bar”代替“foo”、、、、、、、、、“bar”。
std::regex re(“[\n()]+”);
//从正则表达式\u标记\u迭代器构造范围结果向量
返回std::vector(
std::sregx_令牌_迭代器(flow.begin(),flow.end(),re,-1),
std::sregex_令牌_迭代器()
);
}

对此,我将使用正则表达式:

#include <regex>

std::vector<std::string> getToken(std::string const &flow) {
  // Delimiter regex. Depending on your desired behavior, you may want to
  // remove the + from it; with the +, it will combine adjacent delimiters
  // into one. That is to say, "foo (\n) bar" will be tokenized into "foo",
  // "bar" instead of "foo", "", "", "", "", "bar".
  std::regex re("[ \n()]+");

  // range-construct result vector from regex_token_iterators
  return std::vector<std::string>(
      std::sregex_token_iterator(flow.begin(), flow.end(), re, -1),
      std::sregex_token_iterator()
    );
}
#包括
std::vector getToken(std::string const&flow){
//分隔符正则表达式。根据所需的行为,您可能需要
//将+从中删除;使用+,它将合并相邻的分隔符
//即“foo(\n)bar”将标记为“foo”,
//用“bar”代替“foo”、、、、、、、、、“bar”。
std::regex re(“[\n()]+”);
//从正则表达式\u标记\u迭代器构造范围结果向量
返回std::vector(
std::sregx_令牌_迭代器(flow.begin(),flow.end(),re,-1),
std::sregex_令牌_迭代器()
);
}

如果仔细考虑所涉及的状态,您可以使用每个字符的逻辑来完成此操作

std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
bool last_was_delim = true;
while (f.get(c))
    if (delims.find(c) != tokens.end())
    {
        tokens.emplace_back(1, c);
        last_was_delim = true;
    }
    else
    {
        if (last_was_delim)
             tokens.emplace_back(1, c); // start new string
        else
             tokens.back() += c; // append to existing string
        last_was_delim = false;
    }
或者,如果您喜欢
goto
语句:

std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
while (f.get(c))
    if (delims.find(c) != tokens.end())
      add_token:
        tokens.emplace_back(1, c);
    else
    {
        tokens.emplace_back(1, c); // start new string
        while (f.get(c))
            if (delims.find(c) != tokens.end())
                goto add_token;
            else
                tokens.back() += c; // append to existing string
    }
std::向量令牌;
std::string delims=“\n()”;
字符c;
而(f.get(c))
if(delims.find(c)!=tokens.end())
添加\u令牌:
代币。放置回(1,c);
其他的
{
tokens.emplace_back(1,c);//开始新字符串
而(f.get(c))
if(delims.find(c)!=tokens.end())
转到添加_令牌;
其他的
tokens.back()+=c;//追加到现有字符串
}

哪个“更容易”去摸索是有争议的…

如果你仔细考虑所涉及的状态,你可以使用每个字符的逻辑来做这件事

std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
bool last_was_delim = true;
while (f.get(c))
    if (delims.find(c) != tokens.end())
    {
        tokens.emplace_back(1, c);
        last_was_delim = true;
    }
    else
    {
        if (last_was_delim)
             tokens.emplace_back(1, c); // start new string
        else
             tokens.back() += c; // append to existing string
        last_was_delim = false;
    }
或者,如果您喜欢
goto
语句:

std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
while (f.get(c))
    if (delims.find(c) != tokens.end())
      add_token:
        tokens.emplace_back(1, c);
    else
    {
        tokens.emplace_back(1, c); // start new string
        while (f.get(c))
            if (delims.find(c) != tokens.end())
                goto add_token;
            else
                tokens.back() += c; // append to existing string
    }
std::向量令牌;
std::string delims=“\n()”;
字符c;
而(f.get(c))
if(delims.find(c)!=tokens.end())
添加\u令牌:
代币。放置回(1,c);
其他的
{
tokens.emplace_back(1,c);//开始新字符串
而(f.get(c))
if(delims.find(c)!=tokens.end())
转到添加_令牌;
其他的
tokens.back()+=c;//追加到现有字符串
}

哪个更容易to grok是有争议的…

但是你没有保存分隔符,它不在你添加到容器中的
标记中?@Nim:目前没有,但我也想保存它们。滚动你自己的没有意义,其他人已经做了艰苦的工作!但是你没有保存分隔符,它不在你添加到容器中的
标记中我们的容器?@Nim:目前还没有,但我也想保存它们。你自己滚没有意义,其他人已经做了艰苦的工作!这确实是个好主意,但如果可能的话,我想避免在lexer中使用正则表达式?这有点不寻常。随你的便,但我有点惊讶你没有被它们淹死。可能是个g确实是个好主意,但如果可能的话,我想避免在lexer中使用正则表达式?这有点不寻常。随你的便,但我有点惊讶你还没有被它们淹没。