使用多个定界符拆分字符串并将其保存到向量中
Spliting a string with multiple delimiter and save it into a vector
我知道有很多主题都存在像我这样的问题,但我找不到特别适合我的问题的正确答案。
我想通过倍数定界符(' '
、'\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);
}
例如,如果我有:
push int32(42)
我想要以下令牌:
push
int32
(
42
)
我会为此使用正则表达式:
#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<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;
}
显然,这考虑了 "(("
或 " "
(两个空格)重复不同的分隔符,分别输入 tokens
。如有必要,请调整口味。
等效地,但是使用流量控制而不是 bool
/不同的 while (f.get(c))
循环处理正在进行的令牌的额外字符:
std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
while (f.get(c))
if (delims.find(c) != tokens.end())
tokens.emplace_back(1, c);
else
{
tokens.emplace_back(1, c); // start new string
while (f.get(c))
if (delims.find(c) != tokens.end())
{
tokens.emplace_back(1, c);
break;
}
else
tokens.back() += c; // append to existing string
}
或者,如果您喜欢 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
}
"easier" 哪个是 grok 值得商榷....
我知道有很多主题都存在像我这样的问题,但我找不到特别适合我的问题的正确答案。
我想通过倍数定界符(' '
、'\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);
}
例如,如果我有:
push int32(42)
我想要以下令牌:
push
int32
(
42
)
我会为此使用正则表达式:
#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<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;
}
显然,这考虑了 "(("
或 " "
(两个空格)重复不同的分隔符,分别输入 tokens
。如有必要,请调整口味。
等效地,但是使用流量控制而不是 bool
/不同的 while (f.get(c))
循环处理正在进行的令牌的额外字符:
std::vector<std::string> tokens;
std::string delims = " \n()";
char c;
while (f.get(c))
if (delims.find(c) != tokens.end())
tokens.emplace_back(1, c);
else
{
tokens.emplace_back(1, c); // start new string
while (f.get(c))
if (delims.find(c) != tokens.end())
{
tokens.emplace_back(1, c);
break;
}
else
tokens.back() += c; // append to existing string
}
或者,如果您喜欢 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
}
"easier" 哪个是 grok 值得商榷....