具有多个定界符的字符串分词器,包括不带 Boost 的定界符
String Tokenizer with multiple delimiters including delimiter without Boost
我需要用 C++ 创建字符串解析器。我尝试使用
vector<string> Tokenize(const string& strInput, const string& strDelims)
{
vector<string> vS;
string strOne = strInput;
string delimiters = strDelims;
int startpos = 0;
int pos = strOne.find_first_of(delimiters, startpos);
while (string::npos != pos || string::npos != startpos)
{
if(strOne.substr(startpos, pos - startpos) != "")
vS.push_back(strOne.substr(startpos, pos - startpos));
// if delimiter is a new line (\n) then add new line
if(strOne.substr(pos, 1) == "\n")
vS.push_back("\n");
// else if the delimiter is not a space
else if (strOne.substr(pos, 1) != " ")
vS.push_back(strOne.substr(pos, 1));
if( string::npos == strOne.find_first_not_of(delimiters, pos) )
startpos = strOne.find_first_not_of(delimiters, pos);
else
startpos = pos + 1;
pos = strOne.find_first_of(delimiters, startpos);
}
return vS;
}
这适用于 2X+7cos(3Y)
(tokenizer("2X+7cos(3Y)","+-/^() \t");
)
但是给出 2X 的运行时错误
我需要非 Boost 解决方案。
我尝试使用 C++ String Toolkit (StrTk) Tokenizer
std::vector<std::string> results;
strtk::split(delimiter, source,
strtk::range_to_type_back_inserter(results),
strtk::tokenize_options::include_all_delimiters);
return results;
但它没有将令牌作为单独的字符串提供。
例如:如果我将输入设为 2X+3Y
输出向量包含
2X+
3岁
可能发生的事情是这在通过时崩溃了 npos
:
lastPos = str.find_first_not_of(delimiters, pos);
只需在循环中添加中断,而不是依赖 while 子句来中断它。
if (pos == string::npos)
break;
lastPos = str.find_first_not_of(delimiters, pos);
if (lastPos == string::npos)
break;
pos = str.find_first_of(delimiters, lastPos);
我创建了一个小函数,可以将字符串拆分为子字符串(存储在向量中),它允许您设置要将哪些字符视为白色space。正常的 whitespace 仍将被视为 whitespace,因此您不必定义它。实际上,它所做的只是将您定义为 whitespace 的字符变成实际的 whitespace (space char ' ')。然后它在流 (stringstream) 中运行它以分离子字符串并将它们存储在向量中。这可能不是您解决这个特定问题所需要的,但也许它可以给您一些想法。
// split a string into its whitespace-separated substrings and store
// each substring in a vector<string>. Whitespace can be defined in argument
// w as a string (e.g. ".;,?-'")
vector<string> split(const string& s, const string& w)
{
string temp{ s };
// go through each char in temp (or s)
for (char& ch : temp) {
// check if any characters in temp (s) are whitespace defined in w
for (char white : w) {
if (ch == white)
ch = ' '; // if so, replace them with a space char (' ')
}
}
vector<string> substrings;
stringstream ss{ temp };
for (string buffer; ss >> buffer;) {
substrings.push_back(buffer);
}
return substrings;
}
如果您能分享一些关于您的环境的信息,那就太好了。你的程序 运行 在我的 Fedora 20 上使用 g++ 输入值 2X 没问题。
循环退出条件被破坏:
while (string::npos != pos || string::npos != startpos)
允许输入,比如 pos = npos 和 startpos = 1。
所以
strOne.substr(startpos, pos - startpos)
strOne.substr(1, npos - 1)
end 不是 npos,所以 substr 不会在它应该停止的地方停止并且 BOOM!
如果 pos = npos 且 startpos = 0,
strOne.substr(startpos, pos - startpos)
活着,但是
strOne.substr(pos, 1) == "\n"
strOne.substr(npos, 1) == "\n"
死了。也是
strOne.substr(pos, 1) != " "
遗憾的是我没时间了,现在无法解决这个问题,但 QuestionC 的想法是对的。更好的过滤。大致如下:
if (string::npos != pos)
{
if (strOne.substr(pos, 1) == "\n") // can possibly simplify this with strOne[pos] == '\n'
vS.push_back("\n");
// else if the delimiter is not a space
else if (strOne[pos] != ' ')
vS.push_back(strOne.substr(pos, 1));
}
我需要用 C++ 创建字符串解析器。我尝试使用
vector<string> Tokenize(const string& strInput, const string& strDelims)
{
vector<string> vS;
string strOne = strInput;
string delimiters = strDelims;
int startpos = 0;
int pos = strOne.find_first_of(delimiters, startpos);
while (string::npos != pos || string::npos != startpos)
{
if(strOne.substr(startpos, pos - startpos) != "")
vS.push_back(strOne.substr(startpos, pos - startpos));
// if delimiter is a new line (\n) then add new line
if(strOne.substr(pos, 1) == "\n")
vS.push_back("\n");
// else if the delimiter is not a space
else if (strOne.substr(pos, 1) != " ")
vS.push_back(strOne.substr(pos, 1));
if( string::npos == strOne.find_first_not_of(delimiters, pos) )
startpos = strOne.find_first_not_of(delimiters, pos);
else
startpos = pos + 1;
pos = strOne.find_first_of(delimiters, startpos);
}
return vS;
}
这适用于 2X+7cos(3Y)
(tokenizer("2X+7cos(3Y)","+-/^() \t");
)
但是给出 2X 的运行时错误
我需要非 Boost 解决方案。
我尝试使用 C++ String Toolkit (StrTk) Tokenizer
std::vector<std::string> results;
strtk::split(delimiter, source,
strtk::range_to_type_back_inserter(results),
strtk::tokenize_options::include_all_delimiters);
return results;
但它没有将令牌作为单独的字符串提供。
例如:如果我将输入设为 2X+3Y
输出向量包含
2X+
3岁
可能发生的事情是这在通过时崩溃了 npos
:
lastPos = str.find_first_not_of(delimiters, pos);
只需在循环中添加中断,而不是依赖 while 子句来中断它。
if (pos == string::npos)
break;
lastPos = str.find_first_not_of(delimiters, pos);
if (lastPos == string::npos)
break;
pos = str.find_first_of(delimiters, lastPos);
我创建了一个小函数,可以将字符串拆分为子字符串(存储在向量中),它允许您设置要将哪些字符视为白色space。正常的 whitespace 仍将被视为 whitespace,因此您不必定义它。实际上,它所做的只是将您定义为 whitespace 的字符变成实际的 whitespace (space char ' ')。然后它在流 (stringstream) 中运行它以分离子字符串并将它们存储在向量中。这可能不是您解决这个特定问题所需要的,但也许它可以给您一些想法。
// split a string into its whitespace-separated substrings and store
// each substring in a vector<string>. Whitespace can be defined in argument
// w as a string (e.g. ".;,?-'")
vector<string> split(const string& s, const string& w)
{
string temp{ s };
// go through each char in temp (or s)
for (char& ch : temp) {
// check if any characters in temp (s) are whitespace defined in w
for (char white : w) {
if (ch == white)
ch = ' '; // if so, replace them with a space char (' ')
}
}
vector<string> substrings;
stringstream ss{ temp };
for (string buffer; ss >> buffer;) {
substrings.push_back(buffer);
}
return substrings;
}
如果您能分享一些关于您的环境的信息,那就太好了。你的程序 运行 在我的 Fedora 20 上使用 g++ 输入值 2X 没问题。
循环退出条件被破坏:
while (string::npos != pos || string::npos != startpos)
允许输入,比如 pos = npos 和 startpos = 1。
所以
strOne.substr(startpos, pos - startpos)
strOne.substr(1, npos - 1)
end 不是 npos,所以 substr 不会在它应该停止的地方停止并且 BOOM!
如果 pos = npos 且 startpos = 0,
strOne.substr(startpos, pos - startpos)
活着,但是
strOne.substr(pos, 1) == "\n"
strOne.substr(npos, 1) == "\n"
死了。也是
strOne.substr(pos, 1) != " "
遗憾的是我没时间了,现在无法解决这个问题,但 QuestionC 的想法是对的。更好的过滤。大致如下:
if (string::npos != pos)
{
if (strOne.substr(pos, 1) == "\n") // can possibly simplify this with strOne[pos] == '\n'
vS.push_back("\n");
// else if the delimiter is not a space
else if (strOne[pos] != ' ')
vS.push_back(strOne.substr(pos, 1));
}