Russian Qt Forum
Ноябрь 24, 2024, 03:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [Решено] Чем бы разбить строку с учетом кавычек?  (Прочитано 7362 раз)
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« : Сентябрь 19, 2016, 11:59 »

Задача: нужно выделить в строке подстроки, ограничивающиеся символами-разделителями. Но есть некоторые тонкости:

- Символы-разделители могут быть разные. Примерный набор: " .,;:-?!/\".
- В строках могут встречаться кавычки. Все что заключено между двумя кавычками - это отдельная подстрока, и символы-разделители в ней остаются как есть (то есть, разбивки внутри таких подстрок делать не нужно, «схлопывать» символы-разделители тоже в таких подстроках ненужно).
- В исходной строке подстрок в кавычках может быть несколько.
- Если кавычек нечетное количество, выделяются подстроки в парных кавычках, и подстрокой считается часть строки со следующего знакосимвола после последней кавычки до конца строки.

Решение нужно с поддержкой кириллицы (UTF-8) для использования в опенсорчной кроссплатформенной Qt-only программе (минимум Linux, Windows, MacOS, FreeBSD, Android). Поэтому что-то наподобе re2c рассматриваю только в том случае, если есть готовое решение по интеграции библиотеки в код программы.


Примеры, как должно работать разбиение:

Код:
0. Строка: Один два, три
Один
два
три

1. Строка: Один, два, три
Один
два
три

2. Строка: Один-два, три
Один
два
три

3. Строка: "Один два" три
Один два
три

4. Строка: "Один-два" три
Один-два
три

5. Строка: "Один-два" "три четыре
Один-два
три четыре

6. Строка: "Один-два" три, "четыре
Один-два
три
четыре

7. Строка: "Один-два" три "четыре! пять"
Один-два
три
четыре! пять
« Последнее редактирование: Сентябрь 20, 2016, 10:50 от xintrea » Записан

Собираю информацию по крупицам
http://webhamster.ru
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Сентябрь 19, 2016, 12:05 »

Придется писать самому, не думаю что аналогичные парсеры найдутся в каких-то библиотеках -- формат самописный
Записан

m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #2 : Сентябрь 19, 2016, 12:08 »

Посмотрите на boost::tokenizer, boost::xpressive, boost::spirit.
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #3 : Сентябрь 19, 2016, 12:35 »

1. регуляркой найти в сроке "окавыченные" строки и добавить их в итоговый QStringList
2. вырезать их из исходной строки 
3. по оставшейся строке пройти посимвольно, разрезая её по разделителям и добавляя их в итоговый QStringList
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #4 : Сентябрь 19, 2016, 13:07 »

QString::split("\"") и обрабатывать каждую вторую строку, бугага Веселый
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 19, 2016, 13:55 »

Мой велик
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #6 : Сентябрь 19, 2016, 14:08 »

boost::tokenizer - всего пара строк:

Код
C++ (Qt)
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
 
 
using namespace std;
using namespace boost;
 
int main()
{
   string str = "Один-два три, четыре, \"четыре с половиной\"  пять \"шесть, семь восемь";
 
   tokenizer<escaped_list_separator<char>> tok(str, escaped_list_separator<char>("\\", ", -", "\""));
   for(auto it = tok.begin(); it != tok.end(); ++it)
       cout << *it << endl;
 
   return 0;
}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #7 : Сентябрь 20, 2016, 10:50 »

Придется писать самому, не думаю что аналогичные парсеры найдутся в каких-то библиотеках -- формат самописный

Все решилось проще, через конечный автомат:

Код:
QStringList FindScreen::textDelimiterDecompose(QString text)
{
  const int len=text.length();

  QStringList list;
  QString buf;
  bool quoted=false;

  QString delimiter=" '.,;:-?!`";
  delimiter.append(QChar::Tabulation);
  delimiter.append(QChar::Nbsp);

  for(int i=0; i<len; i++)
  {
    // Если обнаружен разделитель
    if(delimiter.contains( text[i] ))
    {
      if( !quoted )
      {
        if(buf.length() > 0)
        {
          list.append(buf);
          buf = "";
        }
      }
      else
        buf += text[i];
    }
    else if(text[i] == '"')
      quoted = !quoted;
    else
      buf += text[i];
  }

  if(buf.length() > 0)
    list.append(buf);

  qDebug() << "Find split list:" << list;

  return list;
}

Все тесты из стартовой мессаги проходят как задумано.

Записан

Собираю информацию по крупицам
http://webhamster.ru
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.137 секунд. Запросов: 23.