Использование escaped_list_separator с разделением буста - PullRequest
4 голосов
/ 21 мая 2009

Я играю с библиотекой надстрочных строк и только что натолкнулся на удивительную простоту метода 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, но у меня уже есть неослабный способ достижения желаемого результата, я просто думаю, что это довольно громоздко, и если бы я не смог заменить его на более простое и элегантное решение, я бы вообще не использовал его без предварительной упаковки в еще один метод.

РЕДАКТИРОВАТЬ: Обновлен код для отображения результатов и уточнения вопроса.

Ответы [ 3 ]

5 голосов
/ 29 мая 2009

Не похоже, что существует какой-либо простой способ сделать это, используя метод 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(","));
2 голосов
/ 19 июня 2012

Это даст тот же результат, что и ответ Джейми Кука без явного цикла.

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

Второй параметр конструктора токенизатора по умолчанию равен escaped_list_separator<char>("\\", ",", "\""), поэтому в этом нет необходимости. Если у вас нет других требований к запятым или кавычкам.

1 голос
/ 21 мая 2009

Я не знаю о библиотеке boost :: string, но с помощью boost regex_token_iterator вы сможете выражать разделители в терминах регулярного выражения. Так что да, вы можете использовать заключенные в кавычки, а также гораздо более сложные вещи.

Обратите внимание, что раньше это делалось с regex_split, который теперь устарел.

Вот пример, взятый из документа Boost:

#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.

Но я подозреваю, что вы хотите иметь дело с такими вещами: "привет", "мир" , и в этом случае одно из решений:

  1. сплит только с комой
  2. затем удалите "" (возможно, используя boost / алгоритма / string / trim.hpp или библиотеку регулярных выражений).

EDIT: добавлен вывод программы

...