4

我正在使用 boost 字符串库,并且刚刚遇到了 split 方法的简单性。

  string delimiters = ",";
  string str = "string, with, comma, delimited, tokens, \"and delimiters, inside a quote\"";
  // If we didn't care about delimiter characters within a quoted section we could us
  vector<string> tokens;  
  boost::split(tokens, str, boost::is_any_of(delimiters));
  // gives the wrong result: tokens = {"string", " with", " comma", " delimited", " tokens", "\"and delimiters", " inside a quote\""}

这会很好而且简洁......但是它似乎不适用于引号,而是我必须做类似以下的事情

string delimiters = ",";
string str = "string, with, comma, delimited, tokens, \"and delimiters, inside a quote\"";
vector<string> tokens; 
escaped_list_separator<char> separator("\\",delimiters, "\"");
typedef tokenizer<escaped_list_separator<char> > Tokeniser;
Tokeniser t(str, separator);
for (Tokeniser::iterator it = t.begin(); it != t.end(); ++it)
    tokens.push_back(*it);
// gives the correct result: tokens = {"string", " with", " comma", " delimited", " tokens", "\"and delimiters, inside a quote\""}

我的问题是,当您引用分隔符时,可以使用拆分或其他标准算法吗?多亏了purpledog,但我已经有了一种不被弃用的方法来实现预期的结果,我只是认为它很麻烦,除非我可以用更简单更优雅的解决方案替换它,否则我一般不会在不先将其包装的情况下使用它另一种方法。

编辑:更新代码以显示结果并澄清问题。

4

3 回答 3

5

使用 boost::split 方法似乎没有任何简单的方法可以做到这一点。我能找到的最短的代码是

vector<string> tokens; 
tokenizer<escaped_list_separator<char> > t(str, escaped_list_separator<char>("\\", ",", "\""));
BOOST_FOREACH(string s, escTokeniser)
    tokens.push_back(s);  

这仅比原始片段稍微详细一点

vector<string> tokens;  
boost::split(tokens, str, boost::is_any_of(","));
于 2009-05-28T22:13:40.533 回答
2

这将达到与 Jamie Cook 没有显式循环的答案相同的结果。

tokenizer<escaped_list_separator<char> >tok(str);
vector<string> tokens( tok.begin(), tok.end() );

标记器构造函数的第二个参数默认为,escaped_list_separator<char>("\\", ",", "\"")因此没有必要。除非您对逗号或引号有不同的要求。

于 2012-06-19T14:30:14.970 回答
1

我不知道 boost::string 库,但使用 boost regex_token_iterator 您将能够用正则表达式表达分隔符。所以是的,您可以使用带引号的分隔符,也可以使用更复杂的东西。

请注意,这曾经是使用 regex_split 完成的,现在已弃用。

这是从 boost doc 中获取的示例:

#include <iostream>
#include <boost/regex.hpp>

using namespace std;

int main(int argc)
{
   string s;
   do{
      if(argc == 1)
      {
         cout << "Enter text to split (or \"quit\" to exit): ";
         getline(cin, s);
         if(s == "quit") break;
      }
      else
         s = "This is a string of tokens";

      boost::regex re("\\s+");
      boost::sregex_token_iterator i(s.begin(), s.end(), re, -1);
      boost::sregex_token_iterator j;

      unsigned count = 0;
      while(i != j)
      {
         cout << *i++ << endl;
         count++;
      }
      cout << "There were " << count << " tokens found." << endl;

   }while(argc == 1);
   return 0;
}

如果程序以hello world作为参数启动,则输出为:

hello
world
There were 2 tokens found.

改变boost::regex re("\s+"); 进入boost::regex re("\",\""); 会拆分带引号的分隔符。以hello","world作为参数启动程序也会导致:

hello
world
There were 2 tokens found.

但我怀疑你想处理这样的事情:"hello", "world",在这种情况下,一种解决方案是:

  1. 仅昏迷分裂
  2. 然后删除“”(可能使用 boost/algorithm/string/trim.hpp 或正则表达式库)。

编辑:添加程序输出

于 2009-05-21T13:38:04.653 回答