Использование escaped_list_separator с разделением повышения

Я играю с библиотекой строк повышения и только что наткнулся на потрясающую простоту метода разделения.

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

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


person Jamie Cook    schedule 21.05.2009    source источник


Ответы (3)


Не похоже, что есть простой способ сделать это с помощью метода 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(","));
person Jamie Cook    schedule 28.05.2009

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

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

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

person Drew Dormann    schedule 19.06.2012

Я не знаю о библиотеке 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.

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

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

РЕДАКТИРОВАТЬ: добавлен вывод программы

person Community    schedule 21.05.2009
comment
Приведенный вами пример будет улучшен, если вы также покажете вывод. Просто чтобы всем, кто найдет эту страницу, было совершенно ясно, что делает этот код. - person A. Levy; 22.05.2009