Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: Igors от Июнь 28, 2012, 18:11



Название: Разбор QString
Отправлено: Igors от Июнь 28, 2012, 18:11
Добрый день

Навеяно этим http://www.prog.org.ru/index.php?topic=22314.msg156566#msg156566 (http://www.prog.org.ru/index.php?topic=22314.msg156566#msg156566). Как всегда, тыкается в нос могучий RegExp но в конце-концов выясняется что почему-то не работает  :'( Накидал простенький класс (аттач) который ни на что не претендует, просто разбирается с кавычками, скобками. Предоставляется "as is"

Краткое описание
Код
C++ (Qt)
// заряжаем параметры разбора
QString delims(" \t");   // 2 символа-разделителя (пробел и табуляция)
QString tokens(",:");   // 2 символа-токена (запятая и двоеточие)
CParseParam param(delims, tokens);
 
// определяем что будет в качестве "цитат" (quote)
param.AddQuote(100, "{", "}");
param.AddQuote(100, "'");
param.AddQuote(0, "\\\"");
param.AddQuote(0, "\"");
 
Пояснения:

1) Символы-разделители - с ними все ясно

2) Символы-токены - то же что и разделители но с той разницей что и сами выдаются в результат. Простой пример запятая
Цитировать
1,3
Определив запятую как символ-разделитель мы получим на выходе 2 строки (1 и 3) и не можем контролировать какой был разделитель, сколько было запятых (одна или больше). Выгоднее иметь запятую как символ-токен

3) Quotes - блокируют символы-разделители и символы-токены. Все внутри quotes, выдается как 1 строка. Quotes имеют приоритет (0 - наивысший). Напр скобки не воспринимаются как quotes если они внутри двойных кавычек приоритет которых выше. Наоборот, кавычки внутри скобок воспринимаются и должны быть сначала закрыты кавычки, а потом скобки.  Quotes c одинаковым приоритетом разбираются в порядке LIFO, напр
Цитировать
"abc de \"fgh" ik
Кавычка после h не закрывает quote - ожидается вложенная кавычка \"

4) Ну и собственно использование
Код
C++ (Qt)
QString str("1, { 2 }, 3");
QStringRef ref;
QStringParser parser(str, param);
while (parser.NextToken(ref))
qDebug() << ref.toString();
 
Любое кол-во парсеров может использовать один и тот же блок параметров разбора. Результат выдается в виде QStringRef (т.е. мы всегда знаем в каком месте исходной строки находимся). Лучше не спешить переводить в QString, а напр можно начать разбор вложенного
Код
C++ (Qt)
if (param.RemoveQuote(ref)) {
QStringRef ref2;
QStringParser parser2(ref, param);
while (parser2.NextToken(ref2))
 ...
}
 


Это все, спасибо за внимание

Edit: последняя версия от 30 июня


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 28, 2012, 18:29
Нужная вещь, спасибо. Интересно ещё, если сравнить скорость выполнения с регуляркой на одинаковых шаблонах.


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 28, 2012, 19:22
Таки разница есть и весьма существенная...

Этот код
Код
C++ (Qt)
QString src="1,2,3,{4,5,6},7,8,9";
QRegExp rx("([^,]|\\{.*\\})");
 
for(int i = 0; i < 1000000; ++i) {
   int pos = 0;
   while((pos = src.indexOf(rx,pos))>=0) {
       pos+=rx.cap(0).length();
   }
}
 
выполнился на моей машине за
real   0m4.570s
user   0m4.520s
sys   0m0.004s

и

real   0m4.563s
user   0m4.548s
sys   0m0.000s

Альтернативный вариант Igors
Код
C++ (Qt)
QString temp, src="1,2,3,{4,5,6},7,8,9";
CParseParam param;
param.AddDelim(",");
param.AddQuote(100, "{", "}");
 
for(int i = 0; i < 1000000; ++i) {
   QStringParser parser(src, param);
   while(parser.NextToken(temp)) {}
}
 
за
real   0m0.939s
user   0m0.928s
sys   0m0.004s

и

real   0m0.928s
user   0m0.920s
sys   0m0.004s


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 28, 2012, 19:27
Единственное, компилятор предупреждение выдал, что параметры mStr и mParam класса QStringParser инициализируются в конструкторе не в том порядке, в котором объявлены. Честно говоря, впервые такое сообщение наблюдаю. Но может от того, что всегда получалось порядок соблюдать.


Название: Re: Разбор QString
Отправлено: Igors от Июнь 29, 2012, 09:27
Почистил, изменения 29 июня

1) Убрал warning компилятора

2) Исправлена ошибка в приоритетах

3) В метод NextToken добавлен параметр stopOnQuoteEnd - возможность извлекать по quote. Пример
Цитировать
{ 1 }{ 2 }
Это "не делится", т.к. нет разделителя между }{. Установив stopOnQuoteEnd мы поделим

4) Добавлены утилитарные методы
CParseParam::QuoteStart - определить что строка начинается с quote
CParseParam::RemoveQuite - убрать bounding quotes (т.е. подготовить суб-строку для разбора)
QStringParser::GetCurDelim - посмотреть на каком разделителе стоим

Таки разница есть и весьма существенная...
А как (каким тулзом) Вы так лихо меряете?


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 29, 2012, 09:49
А как (каким тулзом) Вы так лихо меряете?
Линуксовой консольной командой time


Название: Re: Разбор QString
Отправлено: trot от Июнь 29, 2012, 10:17
Выступлю в защиту регулярных выражений.
Во-первых, выражение
Цитировать
QRegExp rx("([^,]|\\{.*\\})");
является "жадным", а значит, с точки зрения быстродействия, достаточно неэффективное.
Если мы боремся за быстродействие, то это выражение нужно переписывать, т.е. избавляться от конструкции .* .
Во-вторых, предложенный вариант Igors решает узконаправленную задачу, и в этом случае да возможно вы добьетесь лучшего быстродействия.
В-третьих, регулярные выражение досточно универсальный и мощный инструмент (если умело им пользоваться) который имеет под собой теоритические основы.
В четвертых, практика показывает, что к этому инструменту редко обращаются, а отсюда вытекают все проблемы (теряется навык, забывается синтаксис и т.д.). Кроме этого пользователь не может четко сформулировать, то что ему надо иметь на выходе и какие варианты исходных данных могут быть. Чаще всего к решению подходят с кандока.
В пятых, не понимаю зачем заново придумывать велосипед. С таким подходом можно отказаться от всех инструментов, которые есть и делать свое, но на это не хватит ни сил ни времени.


Название: Re: Разбор QString
Отправлено: Bepec от Июнь 29, 2012, 10:24
Регулярные выражения - как двухметровый нож для хлеба :D

Нужны - редко.
Зачастую нужно просто скобочки разбить, да надёргать значений.
Возможностей дофига, но зачастую обычно они не нужны.
Медленные - да. Изза количества возможностей :)
И забываются быстро :/ Я вот уже с трудом напишу регексп средненький.

То есть - хороший, прекрасно заточенный, тяжеленный, гибкий, двухметровый нож для хлеба :D

Вот ток зачастую нужен карманный 5 см :)


Название: Re: Разбор QString
Отправлено: Пантер от Июнь 29, 2012, 10:28
Регулярки универсальны, в этом их плюс.


Название: Re: Разбор QString
Отправлено: DmitryM от Июнь 29, 2012, 10:48
Медленные - да. Изза количества возможностей :)
Обычно регекспы реализуются конечными автоматами, которые хорошо оптимизированы, поэтому может получиться так, что регекспы работают быстрее самописного парсера.


Название: Re: Разбор QString
Отправлено: GreatSnake от Июнь 29, 2012, 10:55
А как (каким тулзом) Вы так лихо меряете?
Отвечу за alexis031182 - time (http://ru.wikipedia.org/wiki/Time_%28Unix%29) )


Название: Re: Разбор QString
Отправлено: Igors от Июнь 29, 2012, 11:35
Отвечу за alexis031182 - time (http://ru.wikipedia.org/wiki/Time_%28Unix%29) )
Я так и знал - это надо что-то набирать в Terminal, для меня это мучение  :'( :'(

В пятых, не понимаю зачем заново придумывать велосипед. С таким подходом можно отказаться от всех инструментов, которые есть и делать свое, но на это не хватит ни сил ни времени.
А разве я против изучить RegExp чтобы потом его применять? Да, выражения выглядят ужасно, но если "надо - так надо". Однако мой энтузиазм охлаждает вот эта фраза из букваря
Цитировать
Note that in general regexps cannot be used to check for balanced brackets or tags.
А у меня этих balanced полным-полно. Чего же я буду изучать и приспосабливать то что для моих целей не предназначено? Да еще хз удастся ли приспособить...

Во-вторых, приведенная в посте #1 ссылка - далеко не единственный пример, где по каким-то причинам RegExp не достигает результата - даже в умелых руках. Получается "изучить и применить" в данном случае совсем не так дешево как хотелось.

В-третьих, поправьте если не так, но я не наблюдаю в RegExp последовательного разбора, т.е. сначала мне нужно расфасовать все по суб-строкам, потом уже заниматься каждой/деталями. Это страшный невдобняк

Ну и чисто "человеческий фактор". Очень может быть что "самописный" вариант коряв и где-то уже есть намного лучший (хотя впрочем необязательно :)). Однако свой текст я прекрасно понимаю, а вот юзая готовый - не очень, фактически запоминается вход-выход, типа "дадим это - получим то-то". Хмм... не вызывает ли это смутное чувство неудовлетворенности, и не потому ли так активно охаивают велосипедистов?  :)

Ладно, завтра будет время - заточу по скорости, а то там в парсере все же зовется malloc - нехорошо


Название: Re: Разбор QString
Отправлено: pastor от Июнь 29, 2012, 12:56
Ладно, завтра будет время - заточу по скорости, а то там в парсере все же зовется malloc - нехорошо

Igors, в коде от 29 числа я ненашел вызова malloc (хотелось бы увидеть контекст использования), поэтому задам более общий вопрос. Чем навеяно то, что malloc медленная функия? Или имелось ввиду что-то дргое?


Название: Re: Разбор QString
Отправлено: Igors от Июнь 29, 2012, 13:19
Igors, в коде от 29 числа я ненашел вызова malloc (хотелось бы увидеть контекст использования), поэтому задам более общий вопрос. Чем навеяно то, что malloc медленная функия? Или имелось ввиду что-то дргое?
Неявно, mStack.push_back его все-таки вызовет. "Медленная" - ну смотря к чему мерять. В данном случае остальной код соразмерим с вызовом malloc, поэтому убрать его есть смысл.


Название: Re: Разбор QString
Отправлено: DmitryM от Июнь 29, 2012, 13:31
Неявно, mStack.push_back его все-таки вызовет. "Медленная" - ну смотря к чему мерять.
Только push_back не всегда вызывает malloc


Название: Re: Разбор QString
Отправлено: trot от Июнь 29, 2012, 14:06
Цитировать
не наблюдаю в RegExp последовательного разбора
Механизм регулярного выражения разбирает строку в один проход последовательно. В общих чертах примерно так: - указтель выставляется на первый символ, далее берется этот символ и сравнивается с шаблоном, если нет совпадения то к первому символу береться второй и опять сравнивается с шаблоном и т.д., дойдя до конца и не найдя совпадения, указатель сдвигается на следующий символ и так далее. Поэтому одним выражением баланс конечно не проверить, а найти после открывающей скобки закрывающую скобку проблем нет. К тому же, если речь идет о балансе, то кавычки и апострофы к этому не имеют никакого отношения.


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 02:14
Доделал, обновил описание (пост #1). Постарался максимально упростить использование (типа "проще = лучше"). Оптимизацию сделал но что достигнуто не проверял

Механизм регулярного выражения разбирает строку в один проход последовательно. В общих чертах примерно так: - указтель выставляется на первый символ, далее берется этот символ и сравнивается с шаблоном, если нет совпадения то к первому символу береться второй и опять сравнивается с шаблоном и т.д., дойдя до конца и не найдя совпадения, указатель сдвигается на следующий символ и так далее. Поэтому одним выражением баланс конечно не проверить, а найти после открывающей скобки закрывающую скобку проблем нет. К тому же, если речь идет о балансе, то кавычки и апострофы к этому не имеют никакого отношения.
Спасибо за объяснение принципов (я этого не знал). Поймите меня правильно, я на RegExp не нападаю. Вполне возможно для делов веба он очень крут - не мне судить. Но для тех разборок что мне нужны он не подходит, и теория и практика это подтверждают. Что значит "кавычки не имеют никакого отношения" (к балансу)? Куда я их дену если они есть, и я должен разобрать учитывая их? Чего я должен искать скобки (которые хз где) - мне нужно получать "теги" один за одним, а там уже смотреть


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 11:11
Тут возможно следует учитывать и саму реализацию парсинга, в нашем случае QRegExp. Скорее всего парсер парсеру рознь. Не факт конечно, но всё же.

А в вебе без регулярок сложно (я о PHP прежде всего, о других языках ничего не могу сказать). И не потому, что там нельзя устроить нечто подобное, что написал Игорь, просто работать это будет относительно медленно. Это на C/C++ можно использовать кучу различных вариантов, чтобы оптимизировать по скорости имеющуюся реализацию, а с пыхпыхом такое не прокатит. Да, есть там строковые функции, выполняющиеся быстрее регулярки, но буде что попадётся для парсинга посложнее, то вся эта альтернатива рассыпется, как карточный домик.


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 11:31
Вот результат ранее использовавшегося шаблона с новым кодом.
Код
C++ (Qt)
QString src="1,2,3,{4,5,6},7,8,9";
 
// заряжаем параметры разбора
CParseParam param(",", "");
 
// определяем что будет в качестве "цитат" (quote)
param.AddQuote(100, "{", "}");
 
QStringParser parser(src, param);
QStringRef ref;
for(int i = 0; i < 1000000; ++i) {
   while (parser.NextToken(ref, true)) {}
}
 
real   0m0.010s
user   0m0.008s
sys   0m0.000s
... и ...
real   0m0.009s
user   0m0.008s
sys   0m0.000s

Ранее было:
real   0m0.939s
user   0m0.928s
sys    0m0.004s


Название: Re: Разбор QString
Отправлено: vregess от Июнь 30, 2012, 12:47
Хороший класс. Спасибо.


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 13:16
Спасибо за промер, был приятно удивлен. Все-таки "размер имеет значение" :) Можно еще ускорить. Сейчас quоtes и символы ищутся линейным перебором, это будет тормозить напр при 20 символах-токенах. Правильно использовать QHash или др ассоциативный контейнер. Ну то на будущее, текущая реализация "не позорная", и этого достаточно.

Понятно что скорость - одна сторона, часто не самая важная. Вот простой фрагмент разборки
Цитировать
...
 },
  "pvp":{
    "ratedBattlegrounds":{
      "personalRating":1141,
      "battlegrounds":[
        {
          "name":"Arathi Basin",
          "played":12,
          "won":9
        },
        {
          "name":"Warsong Gulch",
          "played":6,
          "won":2
        }
      ]
    },
    "arenaTeams":[
      {
        "name":"lkjnhgcx",
        "personalRating":480,
        "teamRating":1504,
        "size":"3v3"
      }
    ],
    "totalHonorableKills":10686
  }
}
Принцип простой: имя-значение, однако значение может быть разных типов, в том числе и массив. Часто лишь некоторые теги надо извлечь. Обычный размер такого файла 20-40k. Очевидно надо сначала выделить тег, затем парить его рекурсивно. Из этих соображений и написан предложенный парсер. А как это с точки зрения регулярных выражений (т.е. подходят ли они здесь) - этого я не знаю, хочу спросить у тех кто владеет техникой регулярок

Спасибо  


Название: Re: Разбор QString
Отправлено: kambala от Июнь 30, 2012, 13:48
исходя из этого примера – неужели существующие JSON-парсеры работают медленее предложенной реализации?


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 14:43
исходя из этого примера – неужели существующие JSON-парсеры работают медленее предложенной реализации?
Ну вот и эрудиты подоспели :) Понятно что если есть формат - есть и парсеры для него, и, наверное, можно "найти и прикрутить". Только вот всегда ли стоит это делать? Тащить буст (или др), чего-то "собирать", перегонять данные, продираться через кучу template - и в конце-концов полагаться на то что "кто-то умный это сделал, значит должно работать". Иногда это неизбежно, но я стараюсь этого по возможности избегать и никогда не понимал испытывающих зверячий кайф от процедуры "прикрутки" :). Не проще ли, используя скромный базовый механизм выделения тегов, накрутить остальное по месту (максимум час) - и все дела?

Однако вернемся к регуляркам. Ссылаясь на др парсер - мы ведь тем самым признаем что регулярки здесь неуместны, не так ли?


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 16:34
Ну вот и эрудиты подоспели :)
Непонятна причина сарказма. Данные в листинге названы своим именем.

Понятно что если есть формат - есть и парсеры для него, и, наверное, можно "найти и прикрутить". Только вот всегда ли стоит это делать?
За редким исключением - да, так как специализированные парсеры как правило хорошо оптимизированы под конкретный формат, проверены временем и уже существуют во всевозможных вариантах реализации. Как говорится, на любой вкус.

Тащить буст (или др), чего-то "собирать", перегонять данные, продираться через кучу template - и в конце-концов полагаться на то что "кто-то умный это сделал, значит должно работать".
На бусте свет клином не сошёлся. Тот же json настолько популярен, что количество вариантов парсеров под него, если и не неимоверно, то где-то рядом точно.

Иногда это неизбежно...
Лучше сказать: "часто это неизбежно, и это хорошо".

... , но я стараюсь этого по возможности избегать и никогда не понимал испытывающих зверячий кайф от процедуры "прикрутки" :).
Таких людей, что любят разбираться в чужом коде, чего-то там прикручивать, изучать кем-то написанное, как раз немного.

Не проще ли, используя скромный базовый механизм выделения тегов, накрутить остальное по месту (максимум час) - и все дела?
Возможно и проще, отчего и написал выше, что бывают исключения. По идее, надо всякий раз делать выбор, исходя из имеющихся условий. Крайность далеко не самый лучший выход.

Однако вернемся к регуляркам. Ссылаясь на др парсер - мы ведь тем самым признаем что регулярки здесь неуместны, не так ли?
Непонятно, к чему такой стиль выбран. Он ведь к холивару приведёт. Лучше рубаните с плеча.

З.Ы. Лично я не любитель регулярок, они всегда мне представлялись слишком тяжёлыми, т.к. уж больно широка вариация. Всегда предпочитал использовать специализированные парсеры.


Название: Re: Разбор QString
Отправлено: kambala от Июнь 30, 2012, 16:48
насколько мне известно, регулярные выражения изначально предназначены для поиска подстрок в тексте, а не для полноценного разбора (например xml, json) и деления на составляющие (токены). они хороши тем, что можно достаточно быстро и кратко записать то, что ты хочешь найти в тексте.

насчёт изобретения велосипедов – мне как раз больше по душе использовать существующие гарантированно работающие решения (повторное использование кода как-никак) нежели писать что-то с нуля. конечно, если какую-то функцию можно быстро набросать в несколько [десятков] строк, то тащить левых библиотек не нужно, но если что-то довольно специфическое, то не вижу смысла сидеть и делать «сизифов труд». аргументы типа «буду знать как оно работает, а не просто доверять какому-то дяде», «получение опыта» уже высказывались неоднократно в разных темах, но далеко не всегда нужно знать внутреннее устройство кода чтобы им пользоваться (инкапсуляция и всё такое).


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 17:44
Понятно что если есть формат - есть и парсеры для него, и, наверное, можно "найти и прикрутить". Только вот всегда ли стоит это делать?
За редким исключением - да, так как специализированные парсеры как правило хорошо оптимизированы под конкретный формат, проверены временем и уже существуют во всевозможных вариантах реализации. Как говорится, на любой вкус.
Мой личный опыт не подтверждает "редкости исключений". Ну вот напр форматик
Цитировать
PathAlignLookAhead 0.033
PathAlignMaxLookSteps 10
PathAlignReliableDist 0.001
IKInitialState 0
SubPatchLevel 0 0
APSDisplay
{ APS
  Version 1
  Method 0
  { VParm
    { ObjectLevel
      0
      { VariantParameter
        3
        0
        { ParameterValue
          0
          0
        }
      }
    }
    { PolygonLevel
      0
      { VariantParameter
        3
        0
        { ParameterValue
          3
          0
        }
      }
    }
    { PolygonPixelSize
      0
      { VariantParameter
        3
        0
        { ParameterValue
          256
          0
        }
      }
    }
  }
}
Конечно нельзя утверждать типа "ну такой парсер Вы точно не найдете!" - но может быть и нет, или ему нельзя верить. И тогда Вы оказываетесь в не очень выгодной ситуации - не хватает велосипеда!

насчёт изобретения велосипедов – мне как раз больше по душе использовать существующие гарантированно работающие решения ..
Это нормально, просто "количество энергии" у (любого) человека ограничено. Чем большим кол-вом тулзов Вы овладеваете - тем меньше места для своих мыслей. И вот когда его остается совсем ноль.. ну надеюсь Вам это не грозит  :)


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 18:29
Мой личный опыт не подтверждает "редкости исключений". Ну вот напр форматик
...
Велосипед рождает необходимость строительства велосипедов.

Конечно нельзя утверждать типа "ну такой парсер Вы точно не найдете!" - но может быть и нет, или ему нельзя верить. И тогда Вы оказываетесь в не очень выгодной ситуации - не хватает велосипеда!
То есть сейчас Вы уже описываете ситуацию с разбором чужого велосипеда. А вот если бы его разработчики сподобились использовать любой из общепринятых форматов, такой проблемы бы не возникло. Обоснование к придумыванию своего формата тем, что, мол, вид данных настолько уникален, что по другому прямо никак, считаю надуманным.

Это нормально, просто "количество энергии" у (любого) человека ограничено. Чем большим кол-вом тулзов Вы овладеваете - тем меньше места для своих мыслей. И вот когда его остается совсем ноль.. ну надеюсь Вам это не грозит  :)
Но можно тогда вообще не изучать чужих тулзов. Тогда места для собственных мыслей будет хоть отбавляй. Мне кажется что-то не слишком верно в Вашей позиции. С точки зрения практичности, лучше использовать существующее решение. Если же условия задачи ставят необходимость модернизации того, что получилось, то можно заняться переработкой каких-то частей кода на предмет эффективности. А может быть код пишется по велению души, так сказать, хобби, тогда конечно сам Бог велел докопаться до сути.


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 19:04
То есть сейчас Вы уже описываете ситуацию с разбором чужого велосипеда. А вот если бы его разработчики сподобились использовать любой из общепринятых форматов, такой проблемы бы не возникло. Обоснование к придумыванию своего формата тем, что, мол, вид данных настолько уникален, что по другому прямо никак, считаю надуманным.
Так там еще 4-5 "под-форматов" (версии) и даже доки нормальной нет (так, "упоминания" в SDK). Но люди этим пользуются, и соответственно возникает необходимость конвертации. Так что, мне сказать "это гнусный нестандартный формат, разбирайтесь сами с этим калом"? Не могу, это работа а не хобби.

Вообще с данными 3D это ситуация типовая: велосипед на велосипеде, стандартов нет. Вот у Qt что-то есть (Qt3D ? - не в курсе) было бы интересно узнать как они хранят данные 3D модели. Подозреваю вряд ли там милый xml, вполне вероятно - тоже велосипед.

Но можно тогда вообще не изучать чужих тулзов. Тогда места для собственных мыслей будет хоть отбавляй. Мне кажется что-то не слишком верно в Вашей позиции. С точки зрения практичности, лучше использовать существующее решение.
А откуда такая безмятежная уверенность что таковое всегда есть и/или обойдется дешевле? :) Вы прекрасно понимаете что я говорю о "золотой середине". Палка перегнута явно в др сторону - бестолковое хватание и заучивание всего подряд - к месту и не к месту.


Название: Re: Разбор QString
Отправлено: Bepec от Июнь 30, 2012, 19:35
Истина познаётся в споре. А выбор между своим велосипедом и чужим решением - сравнением :D

PS эт уже каждый решает для себя, что выбрать. Споры тут неуместны.


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 19:36
Так там еще 4-5 "под-форматов" (версии) и даже доки нормальной нет (так, "упоминания" в SDK). Но люди этим пользуются, и соответственно возникает необходимость конвертации.
Ну значит это Ваш частный случай. Возможно, что область деятельности весьма специфическая.

Так что, мне сказать "это гнусный нестандартный формат, разбирайтесь сами с этим калом"? Не могу, это работа а не хобби.
Нет, столь радикальных рекомендаций я не давал. Обсуждается ведь, как я понимаю, то, что следует предпочесть в ситуации, когда есть выбор, правильно? Если мы не можем использовать существующее решение, исходя из условий задачи (формат данных левый, нет соответствия требованиям к скорости и т.п.), то начинаем собственную разработку, либо производим рефакторинг имеющегося кода. А сразу писать своё просто потому, что оно ближе к сердцу, так это чистой воды удовлетворение собственных амбиций (в хорошем смысле, конечно).

Вообще с данными 3D это ситуация типовая: велосипед на велосипеде, стандартов нет. Вот у Qt что-то есть (Qt3D ? - не в курсе) было бы интересно узнать как они хранят данные 3D модели. Подозреваю вряд ли там милый xml, вполне вероятно - тоже велосипед.
Не в курсе. Но наверняка есть общепризнанные форматы гигантов в этой индустрии, например того же Autodesk. Много свободных приложений для работы с 3D. Я не думаю, что ситуация прямо настолько плачевна.

А откуда такая безмятежная уверенность что таковое всегда есть и/или обойдется дешевле? :) Вы прекрасно понимаете что я говорю о "золотой середине". Палка перегнута явно в др сторону - бестолковое хватание и заучивание всего подряд - к месту и не к месту.
Одна крайность спешит навстречу другой. Баланс энергий, если угодно. Конечно мы оба понимаем, что решение принимается индивидуально в каждом конкретном случае. Просто Вы категорично обозначили вариант как единственно верное решение:
Цитата: Igors
Это нормально, просто "количество энергии" у (любого) человека ограничено. Чем большим кол-вом тулзов Вы овладеваете - тем меньше места для своих мыслей. И вот когда его остается совсем ноль...
Оно и родило такой адекват. Не мною, так кем-нибудь другим был бы обозначен ответ.


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 19:39
Истина познаётся в споре.
Да не, это философская отмазка, лишь бы не работать :)

А выбор между своим велосипедом и чужим решением - сравнением :D

PS эт уже каждый решает для себя, что выбрать. Споры тут неуместны.
Часто действительно интересно написать своё. У меня сейчас как раз такая ситуация с моим проектом веб-сервера.


Название: Re: Разбор QString
Отправлено: Igors от Июнь 30, 2012, 20:52
Обсуждается ведь, как я понимаю, то, что следует предпочесть в ситуации, когда есть выбор, правильно?
А этот выбор часто бывает непростым. Ну конечно, если налицо json - обидеть велосипедиста может каждый :). Но вот задача не имеет столь явных аналогий, напр http://www.prog.org.ru/index.php?topic=21746.msg151303#msg151303 (http://www.prog.org.ru/index.php?topic=21746.msg151303#msg151303). И вот уже почему-то мы автоматически считаем что "готовое решение" = RegExp. Но так ли это? Я лично не уверен, во всяком случае мне это легче сделать просто на С++.

А в более сложных случаях все намного хуже. Увы, слишком поздно обнаруживается что "готовое решение" было ошибкой, и приходится начинать чуть ли не с нуля. с растраченными деньгами и временем  :'(  Использовать готовое конечно заманчиво, но здесь легко потерять "реализьм"


Название: Re: Разбор QString
Отправлено: alexis031182 от Июнь 30, 2012, 21:29
А этот выбор часто бывает непростым. Ну конечно, если налицо json - обидеть велосипедиста может каждый :)
А обидят потому, что хотя и не знают доподлинно возможностей велосипедиста, тем не менее в подавляющем большинстве случаев, в итоге, окажутся правы. Мол, да я! Да я этот json своим самописным парсером порву как болонка грелку! А на поверку оказывается... что ничего не оказывается. Видимо со временем таковые возгласы и сформировали устойчивое общественное мнение о подобных "грандиозных" начинаниях. Да Вы и сами где-то высказывали аналогичную мысль. Кажется в теме о Qt креаторе.

А вот здесь получилось иначе. Вы однозначно доказали, что Ваше решение эффективнее, нежели чем QRegExp (не регулярка как таковая, парсеров, её реализующих, довольно много, но именно кьютишный класс). Отсюда и результат: возгласов супротив нет. Вполне возможно, что кто-нибудь расстроится, если Ваш проект победит в эффективности и некоторых из специализированных парсеров (тех же json), но ломать стереотипы часто полезно. Здесь не могу с Вами не согласиться.

Но вот задача не имеет столь явных аналогий, напр http://www.prog.org.ru/index.php?topic=21746.msg151303#msg151303 (http://www.prog.org.ru/index.php?topic=21746.msg151303#msg151303). И вот уже почему-то мы автоматически считаем что "готовое решение" = RegExp. Но так ли это? Я лично не уверен, во всяком случае мне это легче сделать просто на С++.
Ну инертность свойственна всем в разной степени. Подчас, если посидеть, подумать, то новая идея может довольно значительно отличаться от обычно предпринимаемых в аналогичных ситуациях методов. Но не всегда включается мозг на поиск альтернативных вариантов, если стандартное решение пророчит успех. Селяви :)

А в более сложных случаях все намного хуже. Увы, слишком поздно обнаруживается что "готовое решение" было ошибкой, и приходится начинать чуть ли не с нуля. с растраченными деньгами и временем  :'(  Использовать готовое конечно заманчиво, но здесь легко потерять "реализьм"
Тут уж наверное только опыт может помочь.


Название: Re: Разбор QString
Отправлено: Igors от Июль 01, 2012, 05:42
А обидят потому, что хотя и не знают доподлинно возможностей велосипедиста, тем не менее в подавляющем большинстве случаев, в итоге, окажутся правы. Мол, да я! Да я этот json своим самописным парсером порву как болонка грелку!
Вот именно такого задорного подхода я жду от молодых пацанов! (ну конечно подкрепленного кодом - хоть частично). Однако же - сами видите  :'( :'(

По правде сказать я вспомнил что это json только когда  Вы сказали. Заказчик попросил меня добавить чтение таких файлов и дал пару ссылок на имеющиеся парсеры. Ну я посидел вечерок, делал примерно как сейчас только на char * и ввод был просто "конкретные скобки". Все получилось, потом правда вылез один баг - не учел вложенные кавычки \". Ну и нафиг мне было связываться с чужим кодом?

А вот здесь получилось иначе. Вы однозначно доказали, что Ваше решение эффективнее, нежели чем QRegExp (не регулярка как таковая, ...
Ничего такого я не доказывал! :) Я считаю что RegExp попросту НЕ ПРЕДНАЗНАЧЕН для "контекстного" разбора, и нечего насиловать тул тыкая его куда не надо. О чем кстати есть вполне внятное упоминание в букваре.


Название: Re: Разбор QString
Отправлено: alexis031182 от Июль 01, 2012, 12:44
Вот именно такого задорного подхода я жду от молодых пацанов! (ну конечно подкрепленного кодом - хоть частично). Однако же - сами видите  :'( :'(
Шаблонность мышления? Но это свойственно, наверное, абсолютному большинству. Невозможно же всё перепроверить/переписать самолично. Хоть какие-то блоки, пусть и самые минимальные, так или иначе всё равно будут исходить из чужих, кем-то уже реализованных мыслей. Другое дело конечно, когда шаблонность принимает вредный масштаб. Это навроде позиции, пытающейся оправдать использование кавалерии во Второй мировой войне.

По правде сказать я вспомнил что это json только когда  Вы сказали.
Сказал kambala. А json в вэбе по популярности, похоже, уже давно оставил позади тот же xml. Практически стандарт де-факто.

Заказчик попросил меня добавить чтение таких файлов и дал пару ссылок на имеющиеся парсеры. Ну я посидел вечерок, делал примерно как сейчас только на char * и ввод был просто "конкретные скобки". Все получилось, потом правда вылез один баг - не учел вложенные кавычки \". Ну и нафиг мне было связываться с чужим кодом?
Вы уверены в своих силах, от того и оправдан был Ваш шаг. Плюс, Вы сами себе хозяин в принятии решений о том, как поступать в этом и похожих случаях. Но представьте положение молодого исполнителя, что не имеет возможности для манёвра. В его ситуации отход от какого-либо постулата чреват срывом заказа. Зачем ему дополнительный риск? Как минимум он потеряет больше времени на разработку собственного решения. А как максимум - его начинание может закончиться признанием поражения. Другими словами, чтобы заняться своей собственной уникальной разработкой, необходимы соответствующие условия. Это, например, и относительная свобода в принятии решения, которая, по правде сказать, автоматически снизит долю ответственности (не может же быть так, что если где-нибудь прибыло, то нигде не убудет). Это и наличие большего количества знаний и опыта по сравнению с ожидаемым заказчиком уровнем исполнителя. Это и... да хотя бы просто наличие здорового авантюризма, поскольку не всегда представляется возможность адекватно оценить собственные силы для не шаблонного решения задачи.

Ничего такого я не доказывал! :) Я считаю что RegExp попросту НЕ ПРЕДНАЗНАЧЕН для "контекстного" разбора, и нечего насиловать тул тыкая его куда не надо. О чем кстати есть вполне внятное упоминание в букваре.
Как раз доказательство Вы и привели. Потребовалась разработка собственного решения, чтобы обстоятельно показать неэффективность применения регулярки, как Вы назвали, для "контекстного разбора". Иначе получился бы чистой воды холивар. Приводилось бы множество малосвязанных между собой примеров, противостоящих точке зрения оппонентов. А тут, раз, и в дамках. Супротив аргумента "скорость выполнения" мало что возможно возразить. Тем более, когда разница столь существенна.


Название: Re: Разбор QString
Отправлено: moskk от Октябрь 05, 2012, 12:02
спасибо автору за труд.
жаль только в коде нет коментов с описанием, они точно бы не помешали.


Название: Re: Разбор QString
Отправлено: m_ax от Май 04, 2013, 19:58
Столкнулся с аналогичной проблемой разбора определённых форматов документов.
И.. вспомнил про эту тему..

Если можно немного покритикую реализацию igors'а.

Во-первых, хотелось бы чтобы это не было завязано на Qt (пишу сейчас ядро и зависимости от такого монстра, как Qt там излишни)

Во-вторых, хотелось бы иметь возможность начинать разбор с определённого места, т.е. чтобы можно было задавать pos (position) с которой начинается разбор. Нечто подобное интерфейсу QRegExp, например..

В общем, первые два пункта, заставили меня написать нечто подобное. Концептуально, интерфейс я старался сохранить близким к реализации igors'а. (приатачено ниже)

И так два класса:
parse_param
Код
C++ (Qt)
class parse_param
{
public:
   parse_param();
   parse_param(const std::string &tokens, const std::string &delims);
 
   void add_quote(char bra, char ket);
   void set_delims(const std::string &delims);
   void set_tokens(const std::string &tokens);
 
   friend class string_parser;
 
private:
   std::string m_bra_list;
   std::string m_ket_list;
   std::string m_tokens;
   std::string m_delims;
};
 
С токенами и делимами здесь, думаю все знакомы. Метод add_quotes добавляет открывающий символ (bra) и закрывающий символ (ket) для цитаты. Всё остальное аналогично варианту igors'а, за исключением того, что в конструкторе вначале передаются токены, а затем делимы.

И интерфейс string_parser:
Код
C++ (Qt)
enum class split_behavior { keep_empty_parts, skip_empty_parts };
 
class string_parser
{
public:
   typedef std::string::size_type size_type;
 
   string_parser(const parse_param &param);
 
   size_type next_token(const std::string &str, size_type pos = 0, split_behavior behavior = split_behavior::skip_empty_parts) const;
   size_type next_quote(const std::string &str, size_type pos = 0, split_behavior behavior = split_behavior::skip_empty_parts) const;
   size_type matched_length() const;
   char token() const;
   std::string result() const;
 
   static std::string trim(const std::string &str, const std::string &delim = " \t\n");
   static size_type npos();
 
private:
   const parse_param &m_param;
   mutable char m_token;
   mutable size_type m_mathed_length;
   mutable std::string m_result;
 
   size_type find_first_token(const std::string &str, size_type pos = 0) const;
   static size_type skip_quote(const std::string &str, char bra, char ket, size_type pos = 0);
};
 
Здесь метод next_token возвращает позицию следующего токена, в противном случае std::string::npos, например:
Код
C++ (Qt)
std::string str = "a, b, , c , {d,e {f}}";
parse_param param(",.", " \t");
param.add_quote('{', '}');
 
string_parser parser(param);
size_t pos = 0;
while ((pos = parser.next_token(str, pos, mbib::split_behavior::skip_empty_parts)) != std::string::npos) {
   std::cout << std::left << parser.result()  << std::setw(10) << parser.token() << std::endl;
   pos += parser.matched_length();
}
 
вывод:
Код
Bash
"a"
","
"b"
","
"c"
","
"{d,e {f}}"
""        
 
Если установлен флаг split_behavior::keep_empty_parts, то будут также выведены все пустые строки между токенами:
Код
C++ (Qt)
std::string str = "a, b, , c , {d,e {f}}";
parse_param param(",.", " \t");
param.add_quote('{', '}');
 
string_parser parser(param);
size_t pos = 0;
while ((pos = parser.next_token(str, pos, mbib::split_behavior::keep_empty_parts)) != std::string::npos) {
   std::cout << std::left << parser.result()  << std::setw(10) << parser.token() << std::endl;
   pos += parser.matched_length();
}
 

вывод:
Код
Bash
"a"
","
"b"
","
""
","
"c"
","
"{d,e {f}}"
""
 
далее, метод next_quote возвращает позицию начала цитаты. Всё остальное аналогично next_token:
Код
C++ (Qt)
std::string str = "{a, b},{}{} , c , {d,e {f}}";
parse_param param(",.", " \t");
param.add_quote('{', '}');
 
string_parser parser(param);
size_t pos = 0;
while ((pos = parser.next_token(str, pos, mbib::split_behavior::skip_empty_parts)) != std::string::npos) {
   std::cout << std::left << parser.result() << std::endl;
   pos += parser.matched_length();
}
 
Вывод:
Код
Bash
"a, b"
"d,e {f}"
 
метод result возвращает строку с результатом,
метод token возвращает текущий символ токена (в противном случае -1)
метод matched_length - аналогичен QRegExp::matchedLength
trim удаляет в начале и в конце строки delims.
npos - аналогичен std::string::npos

Теперь о тестах и о производительности.
Сравнивались реализация igors и моя на следующем простом примере:
Код
C++ (Qt)
#include <iostream>
#include <ctime>
#include "string_parser.h"
#include "QStringParser.h"
#include <QDebug>
 
int main()
{
   QString src="Westerholt, K.  {and Sprungmann, D.}  and Zabel, H.  and Brucas, R.  and Hj\"orvarsson, B.  and Tikhonov, D. A. and Garifullin, I. A.";
   std::string std_src = src.toStdString();
   const long N = 1000000;
 
   parse_param param(",.", " \t");
   param.add_quote('{', '}');
 
   string_parser parser(param);
 
   clock_t tStart = clock();
   for (long i = 0; i < N; ++i) {
       size_t pos = 0;
       while ((pos = parser.next_token(std_src, pos, split_behavior::keep_empty_parts)) != std::string::npos) {
           //std::cout << parser.result() << std::endl << parser.token() << std::endl;
           pos += parser.matched_length();
       }
   }
   std::cout << "m_ax: time (sec) = " << (float)(clock() - tStart) / CLOCKS_PER_SEC << std::endl;
 
 
   CParseParam cparam(" \t", ",.");
   cparam.AddQuote(100, "{", "}");
 
   QStringRef temp;
   tStart = clock();
   for (long i = 0; i < N; ++i) {
       QStringParser cparser(src, cparam);
       while(cparser.NextToken(temp)) {}
   }
   std::cout << "igors: time (sec) = " << (float)(clock() - tStart) / CLOCKS_PER_SEC << std::endl;
 
   return 0;
}
 

Вывод на моей машине:
Код
Bash
m_ax: time (sec) = 11.72
igors: time (sec) = 8.93
 

Как видно, производительность у обоих реализаций практически одинаковая.

Проект приатачен, спасибо за внимание).



 
       


Название: Re: Разбор QString
Отправлено: Igors от Май 05, 2013, 10:41
Если можно немного покритикую реализацию igors'а.

Во-первых, хотелось бы чтобы это не было завязано на Qt (пишу сейчас ядро и зависимости от такого монстра, как Qt там излишни)

Во-вторых, хотелось бы иметь возможность начинать разбор с определённого места, т.е. чтобы можно было задавать pos (position) с которой начинается разбор. Нечто подобное интерфейсу QRegExp, например..
Критиковать можно и нужно  :)

1) С определенного места (или фрагмент) можно, ведь используется QStringRef - очень удобный утилитарный класс, и надо было просто передрать его для std::string реализации. Возвращение позиции (индекса) куда менее удобно, возникают заботы о конце.

2) Не понял (может просто невнимательно смотрел) как Вы обошлись без приоритетов quote. Напр

"test ("test)  // одна quote кавычки, другая скобки ()

Также если баланс quote нарушен (напр "test) то возвращаемым токеном должно быть все до конца строки (а не npos) 

Вообще самое трудное в этой задаче - не реализация, а придумать как этим удобно пользоваться. В связи с этим какая-я то обобщенная реализация (напр для QString и std::string) наверно была бы совершенно монструозной  :)


Название: Re: Разбор QString
Отправлено: m_ax от Май 05, 2013, 12:36
Если можно немного покритикую реализацию igors'а.

Во-первых, хотелось бы чтобы это не было завязано на Qt (пишу сейчас ядро и зависимости от такого монстра, как Qt там излишни)

Во-вторых, хотелось бы иметь возможность начинать разбор с определённого места, т.е. чтобы можно было задавать pos (position) с которой начинается разбор. Нечто подобное интерфейсу QRegExp, например..
Критиковать можно и нужно  :)

1) С определенного места (или фрагмент) можно, ведь используется QStringRef - очень удобный утилитарный класс, и надо было просто передрать его для std::string реализации. Возвращение позиции (индекса) куда менее удобно, возникают заботы о конце.

2) Не понял (может просто невнимательно смотрел) как Вы обошлись без приоритетов quote. Напр

"test ("test)  // одна quote кавычки, другая скобки ()

Также если баланс quote нарушен (напр "test) то возвращаемым токеном должно быть все до конца строки (а не npos) 

Вообще самое трудное в этой задаче - не реализация, а придумать как этим удобно пользоваться. В связи с этим какая-я то обобщенная реализация (напр для QString и std::string) наверно была бы совершенно монструозной  :)

По-поводу п. 2
С приоритетами, имхо, это лишнее.. Это порождает неоднозначные ситуации, и скорее, свидетельствует о плохо определённом формате..
Позже поясню..



Название: Re: Разбор QString
Отправлено: Bepec от Май 05, 2013, 13:37
Я так думаю, что ситуация с приоритетом возможна при порче строки. И из этой ситуации  класс должен выходить победителем :P


Название: Re: Разбор QString
Отправлено: Old от Май 05, 2013, 14:52
Я так думаю, что ситуация с приоритетом возможна при порче строки. И из этой ситуации  класс должен выходить победителем :P
Из этой ситуации есть только один выход: завершить программу с сообщением об ошибке. :)


Название: Re: Разбор QString
Отправлено: Bepec от Май 05, 2013, 15:22
Почему же? если ошибка находится в секции, которая не требуется обязательно для работы, то вполне можно и запуститься и сообщить об ошибке и, возможно, произвести работы по восстановлению ;P


Название: Re: Разбор QString
Отправлено: m_ax от Май 05, 2013, 22:02
И так, по поводу приоритетов..

Меня, как пользователя, смутило следующее:

1) Неочевидность.. Казалось бы, чем выше приоритет для quote,  тем выше по иерархи она должна стоять (ну и обрабатываться).. У вас же всё наоборот..

2) Непонятное (?) поведение для такого простого примера:
Код
C++ (Qt)
   QString src = "\"test, (\",test)";
   CParseParam cparam(" \t", ",.");
   cparam.AddQuote(10, "(", ")");
   cparam.AddQuote(10, "\"", "\"");
 
   QStringRef temp;
   QStringParser cparser(src, cparam);
    while(cparser.NextToken(temp)) {
        qDebug() << temp;
    }
 
Почему вывод будет таким:
Код
Bash
""test, (",test)"
 
Ведь приоритеты для обоих цитат одинаковы..
Логичнее было бы ожидать такого результата:
Код
Bash
""test, (""
","
"test)"
 
Это понятно почему логичнее?

3) Эта излишняя "универсальность" + неочевидность может в конечном счёте привести к тому, что распарсите вы совсем не то, чего ожидаете, просто от банальной ошибки в формате (скобку там кто-нить лишнюю поставил, или, наоборот, забыл про неё) Опять же имхо, но такая возможность с ними (приоритетами) как бэ поощряет "кривые форматы".. и как, следствие, очередные велосипеды..

Но всё это, конечно, наверное, больше дело личных предпочтений.. В конечном счёте вам решать.. Я лишь высказал личное впечатления и своё видение этого.

Я так думаю, что ситуация с приоритетом возможна при порче строки. И из этой ситуации  класс должен выходить победителем :P

Да здесь таких проблем и нет.. Если при разборе больше нет соответствий, то парсинг прекращается, а дальше уже конечному пользователю решать что делать. Вся информация о проблемном месте у него будет..

  
 
 


Название: Re: Разбор QString
Отправлено: Igors от Май 06, 2013, 09:13
1) Неочевидность.. Казалось бы, чем выше приоритет для quote,  тем выше по иерархи она должна стоять (ну и обрабатываться).. У вас же всё наоборот..
Дело вкуса - можно напр вспомнить "0 = уровень ядра (наивысший)"

Логичнее было бы ожидать такого результата:
Не "логичнее" а "интуитивнее" т.к. в жизни приоритет кавычек выше. Так никто Вам не мешал дать такой приоритет как в жизни. Возьмем квадратные скобки вместо кавычек
Код
C++ (Qt)
QString src = "[test(],test)]";
 
С какой же стати первый токен должен быть [test, (]? Проблемы внутри круглых скобок, до этого должны выдаться нормальные токены test и (],test)

3) Эта излишняя "универсальность" + неочевидность может в конечном счёте привести к тому, что распарсите вы совсем не то, чего ожидаете, просто от банальной ошибки в формате (скобку там кто-нить лишнюю поставил, или, наоборот, забыл про неё) Опять же имхо, но такая возможность с ними (приоритетами) как бэ поощряет "кривые форматы".. и как, следствие, очередные велосипеды..
Это обычная лень и нежелание вникать в какие-то там тонкости  :)

Непонятно как Вы обойдетесь без приоритета здесь
test("some)thing")

Или даже здесь (не вижу как у Вас это отрабатывается)
test("something()")


Название: Re: Разбор QString
Отправлено: m_ax от Май 06, 2013, 09:59
Не "логичнее" а "интуитивнее" т.к. в жизни приоритет кавычек выше. Так никто Вам не мешал дать такой приоритет как в жизни. Возьмем квадратные скобки вместо кавычек
Код
C++ (Qt)
QString src = "[test(],test)]";
 
С какой же стати первый токен должен быть [test, (]? Проблемы внутри круглых скобок, до этого должны выдаться нормальные токены test и (],test)
Ещё раз: Здесь у вас квадратные и круглые скобки имеют одинаковый приоритет, т.е. фактически, они равноправны. Почему вы делаете выбор в пользу круглых скобок, а не квадратных? Ведь первая цитата начинается именно с них (с квадратных). 

Цитировать
Непонятно как Вы обойдетесь без приоритета здесь
test("some)thing")

Или даже здесь (не вижу как у Вас это отрабатывается)
test("something()")
Да легко, в зависимости от того, что мне нужно будет получить.


Название: Re: Разбор QString
Отправлено: Igors от Май 06, 2013, 10:40
Ещё раз: Здесь у вас квадратные и круглые скобки имеют одинаковый приоритет, т.е. фактически, они равноправны. Почему вы делаете выбор в пользу круглых скобок, а не квадратных? Ведь первая цитата начинается именно с них (с квадратных).
Ничего я не делаю. Мой разбор должен работать так  
[test(],test)]  // первый вернул все в квадратных скобках (включая их)
test + (],test)   // второй вернул 2 токена
] + , + test  // третий

Что не так?

Цитировать
Непонятно как Вы обойдетесь без приоритета здесь
test("some)thing")

Или даже здесь (не вижу как у Вас это отрабатывается)
test("something()")
Да легко, в зависимости от того, что мне нужно будет получить.
Предъявляем результаты Вашего парсера  :)

Ещё раз:
..
Да легко,
Меньше зазнайства = лучше  :)


Название: Re: Разбор QString
Отправлено: m_ax от Май 06, 2013, 11:42
Ещё раз: Здесь у вас квадратные и круглые скобки имеют одинаковый приоритет, т.е. фактически, они равноправны. Почему вы делаете выбор в пользу круглых скобок, а не квадратных? Ведь первая цитата начинается именно с них (с квадратных).
Ничего я не делаю. Мой разбор должен работать так  
[test(],test)]  // первый вернул все в квадратных скобках (включая их)
test + (],test)   // второй вернул 2 токена
] + , + test  // третий

Что не так?

Похоже, у нас с вами немного разные представления о том, что такое quote и о том, как она должна интерпретироваться.
Для меня quote - это то, что заключено между первым открывающим цитату (bra символом) и закрывающим её (ket символом). Причём баланс bra и ket символов должен быть одинаков. При этом любой другой bra символ не имеет права экранировать ket символ принадлежащий другой паре (bra, ket ).
Например такая ситуация:
Код
C++ (Qt)
   std::string std_src = "author = {Singh, A. and S\"urgers, C. },\n year = \"2013\"\n ";
   parse_param param(",=", " \t\n");
   param.add_quote('{', '}');
   param.add_quote('"','"');
 
   string_parser parser(param);
   size_t pos = 0;
   while ((pos = parser.next_token(std_src, pos, split_behavior::keep_empty_parts)) != std::string::npos) {
       std::cout << parser.result() << std::endl << parser.token() << std::endl;
       pos += parser.matched_length();
    }
 
Даст вполне ожидаемый результат:
Код
Bash
author
=
{Singh, A. and S"urgers, C. }
,
year
=
"
2013"


В то время, как ваш вариант (с равными приоритетами) распарсит это совсем по другому (что противоречит здравому смыслу)
Код
C++ (Qt)
   QString src = "author = {Singh, A. and S\"urgers, C. },\n year = \"2013\"\n ";
   CParseParam cparam(" \t\n", ",=");
   cparam.AddQuote(10, "{", "}");
   cparam.AddQuote(10, "\"", "\"");
 
   QStringRef temp;
   QStringParser cparser(src, cparam);
    while(cparser.NextToken(temp)) {
       qDebug() << temp;
   }
 
Вывод будет таким:
Код
Bash
"author"
"="
"{Singh, A. and S"urgers, C. },
year = "2013"
"

Эти приоритеты, в том виде, в котором они у вас реализованы, имхо, только лишь запутывают..

Цитировать
Предъявляем результаты Вашего парсера  
Опять-таки, в зависимости от интерпретации формата. Там какая то каша (в первом варианте) + не понятно что нужно извлечь.. Неоднозначность, о которой я уже писал и которую поощрять, подобными приоритетами, может быть чревато..


Название: Re: Разбор QString
Отправлено: m_ax от Май 06, 2013, 12:35
Я понимаю зачем вам нужны эти приоритеты.. Я к тому, что нужно определить правила игры так, чтоб это было очевидно и не приводило к неоднозначным ситуациям..


Название: Re: Разбор QString
Отправлено: Igors от Май 06, 2013, 12:41
Похоже, у нас с вами немного разные представления о том, что такое quote и о том, как она должна интерпретироваться.
Для меня quote - это то, что заключено между первым открывающим цитату (bra символом) и закрывающим её (ket символом). Причём баланс bra и ket символов должен быть одинаков. При этом любой другой bra символ не имеет права экранировать ket символ принадлежащий другой паре (bra, ket ).
По жизни: все что в кавычках (строка, литерал) должно рассматриваться как 1 токен - железно, независимо от того что там слева и справа от кавычек. Что значит "не имеет права"? Типа "работаем только с корректными данными, пусть, мол, юзверь обеспечит баланс и тогда..". Это несерьезно  :)

Опять от жизни/практики: вложенная кавычка (я за это получал по ушам в том же json)

QString src("Weapon \\\"test\\\");
Weapon \"test\"   // в читабельном виде

А Вы отпихнулись одним символом начала и конца (bra + ket).

Еще реальный пример - разрушен баланс тех же скобок. Чего это Вы так весело выдаете npos - это ж нет больше данных? А они есть - и об ошибке надо сообщать (а не сачковать)

Эти приоритеты, в том виде, в котором они у вас реализованы, имхо, только лишь запутывают..
Я не против если Вы предложите лучшую реализацию, но приоритеты экранирования в жизни есть - и попытка обойтись вообще без них, на мой взгляд, несостоятельна.


Название: Re: Разбор QString
Отправлено: m_ax от Май 13, 2013, 16:26
Да, и ещё об определениях, что есть токены и что есть делимы:

token - one piece of information, a "word"
delimiter - one (or more) characters used to separate tokens

 


Название: Re: Разбор QString
Отправлено: m_ax от Июль 03, 2013, 17:49
Кстати, решение предложенное в boost::tokinizer http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/ (http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/) (точнее, как он архитектурно устроен) гораздо более гибкое и расширяемое, чем реализации предложенных здесь велосипедов.

Например, для разбивки на токены:
Код
C++ (Qt)
std::string str = "text1, text2: text3, text4";
boost::tokenizer<boost::char_separator<char>> tok(str, boost::char_separator<char>(",:"));
for (auto it = tok.begin(); it != tok.end(); ++it)
   std::cout << *it << std::endl;
 
где boost::char_separator - это класс, реализующий алгоритм разбиения строки, где  разделители dropped_delims являются простыми символами (char, как в примере).  

Также в boost::tokenizer входят такие алгоритмы как:
escaped_list_separator  http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/escaped_list_separator.htm (http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/escaped_list_separator.htm)
и
offset_separator http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/offset_separator.htm (http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/offset_separator.htm)

К сожалению ни один из них не реализует полную поддержку работы с цитатами (escaped_list_separator - предоставляет только частный случай), как обсуждалось здесь выше.
Однако, архитектурное решение boost::tokenizer очень гибкое и позволяет реализовать пользовательский алгоритм разбиения строки на токены.
При этом интерфейс  tokenizerа и работа с ним останется неизменными.

И так для реализации своего алгоритма нужно написать свой класс, где должны быть определены два метода (смотрим исходники boost token_functions.hpp):

Код
C++ (Qt)
enum class empty_token_policy { drop_empty_tokens, keep_empty_tokens };
 
template <class CharT>
class simple_char_separator
{
public:
   typedef std::basic_string<CharT> string_type;
   typedef typename string_type::const_iterator const_iterator;
 
   void reset() {}
 
    bool operator()(const_iterator & next, const_iterator end, string_type & tok) const {
 
   }
 
};
 
Фактически, сам алгоритм реализуется в   bool operator()(const_iterator & next, const_iterator end, string_type & tok). Здесь end указывает на конец строки, а next - текущий итератор. Этот метод вызывается при каждой итерации, результат записывается в tok и итератор next также продвигается к следующей позиции. Итерации продолжаются до тех пор, пока метод возвращает true.
Вобщем, всё просто)

Ниже привожу пример своей реализации, поддерживающей цитаты. Пример использования:
Код
C++ (Qt)
#include <iostream>
#include "core/spec_token_functions.h"
#include <boost/tokenizer.hpp>
 
int main()
{
   std::string str = "text1, {text2, text3.} : text4. \"text5, abs\" ";
 
   bibmake::core::quote_list<char> quotes('{', '}');
   quotes.add_quote('"', '"');
 
   std::string dropped_delims = ",.";
   std::string kept_delims = ":";
 
   typedef bibmake::core::spec_char_separator<char> spec_char_separator;
   boost::tokenizer<spec_char_separator> tok(str, spec_char_separator(dropped_delims, kept_delims, quotes));
   for (auto s : tok) {
       std::cout << s << std::endl;
   }
 
   return 0;
}
 
где вывод будет такой:
Код
Bash
text1
{text2, text3.}
:
text4
"text5, abs"
 

Реализация spec_token_functions приатачена)




 




  


Название: Re: Разбор QString
Отправлено: Bepec от Июль 03, 2013, 17:53
Не в обиду вас, m_ax будет сказано, но после прочтение второй строчки code у меня появилось стойкое ощущение что я читаю что-то явно неправильное :D

А такое ощущение у меня обычно появляется когда разбираю библиотеку "нарисовать линию", в которой имеется функционал построение звезды смерти в 3D.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 03, 2013, 18:06
Не в обиду вас, m_ax будет сказано, но после прочтение второй строчки code у меня появилось стойкое ощущение что я читаю что-то явно неправильное :D

А такое ощущение у меня обычно появляется когда разбираю библиотеку "нарисовать линию", в которой имеется функционал построение звезды смерти в 3D.

А что именно не понятно? У меня, когда я первое время смотрел boost, тоже складывалось стойкое ощущение.. хм..)
Но со временем привыкаю) Всё же в решения в booste очень грамотно спроектированы) Не в обиду igors'у  ;)  


Название: Re: Разбор QString
Отправлено: Igors от Июль 03, 2013, 19:52
Кстати, решение предложенное в boost::tokinizer http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/ (http://www.boost.org/doc/libs/1_54_0/libs/tokenizer/) (точнее, как он архитектурно устроен) гораздо более гибкое и расширяемое, чем реализации предложенных здесь велосипедов.
Можно сказать проще
Цитировать
ЛЮБОЕ рещение в бусте ЛУЧШЕ, гибче и.т.п. ЛЮБОГО своего решения
С этим трудно спорить - напр мой парсер годится только для QString, а дустовский наверняка для любого строчника - уже лучше. Но может быть Вас еще смущает что звучит это утверждение как-то "не очень хорошо" - ведь так может сказать и просто лох, из простых соображений типа "буст - солидная, авторитетная либа, а ты хто такой?"  :)

В действительности не все так просто. Наверняка Вы замечали что далеко не все форумчане горят желанием юзать буст. Ах, глупые, ленивые, "не хотят учиться" и.т.п. Глупости. Реальные причины другие

- порог вхождения длстаточно высок. На освоение бустовского решения Вы затратили не меньше времени чем на написание своего

- было бы хорошо если просто "раз выучил - навсегда пользуйся". Однако так происходит не всегда.  Напр для поддержки цитат Вам пришлось написать кусок кода вполне соразмеримый с "велосипедом"

- самое главное, и самое страшное: дальнейшая ПОДДЕРЖКА этого кода. Возможно то что Вы написали - гораздо лучше, грамотнее и.т.п. (впрочем необязательно). Но поверьте, в проекте это PITA (pain in the ass). Потому что для хоть каких-то дальнейших изменений будет печальный выбор:
   - нанимать бойца владеющего дустом (который будет воротить морду и требовать высоких гонораров)
   - переключить имеющихся работников на фиксацию (связанную с изучением всех этих вумностей)
И то и другое обойдется недешево. С др стороны - так ли уж необходим столь изощренно-обобщенный код? На примере той же задачи (разбор скобок/цитат) я Вам точно скажу - нет. Это скромная утилитарная задача, и платить за нее заказчик хочет адекватно. Привлекая "слишком мощные средства" мы только создаем проблемы.

Ну и вообще - это становится глупой самоцелью. Возникает иллюзия что все что угодно можно "освоить" усилиями памяти - но не ума. Ах да, "все уже давно написано". Но это справедливо только для довольно узкого круга простых и/или известных задач. К сожалению "емкость мозга" ограничена - чем больше он набрался всякой всячины - тем более он беспомощен когда приходится думать/решать самому. Увы, по-видимому это неизбежно  :'(


Название: Re: Разбор QString
Отправлено: Old от Июль 03, 2013, 19:56
чем больше он набрался всякой всячины - тем более он беспомощен когда приходится думать/решать самому.
Это не правда. Все в точности наоборот. :)

- порог вхождения длстаточно высок. На освоение бустовского решения Вы затратили не меньше времени чем на написание своего
Тоже не правда. Любой программист C++ (внимание не С с классами), а грамотный программист, спокойно пользуется большинством бустовских библиотек. Именно поэтому она так популярна. То, что она не очень популярна на форуме Qt и так понятно, в Qt есть много своих аналогичных решений.

- самое главное, и самое страшное: дальнейшая ПОДДЕРЖКА этого кода. Возможно то что Вы написали - гораздо лучше, грамотнее и.т.п. (впрочем необязательно). Но поверьте, в проекте это PITA (pain in the ass). Потому что для хоть каких-то дальнейших изменений будет печальный выбор:
   - нанимать бойца владеющего дустом (который будет воротить морду и требовать высоких гонораров)
   - переключить имеющихся работников на фиксацию (связанную с изучением всех этих вумностей)
Это чудо аргумент.  ;D
Вас не смущает, что если нужно написать GUI, то нужно нанимать бойца умеющего Qt/wxWidget/GTK/..., который будет воротить морду и требовать высокий гонорар? Или переключать имеющегося сотрудника на фиксацию связанную с GUI? Тогда почему вас смущает боец с boost? В чем для вас разница между Qt и boost (ну кроме того, что с первой вы справились, а со второй нет)? :)

Вас эти решения не устраивают только по одной причине - вы не смогли/захотели освоить boost, а теперь хотите красиво за это оправдаться. Только зачем?


Название: Re: Разбор QString
Отправлено: Bepec от Июль 03, 2013, 20:04
Я лично отношусь к обществу описанному Igors.

Мне трудно с бустом. К примеру те же самые рег экспы я не смог освоить в бусте за полчаса. Скачав библиотечку в виде 1 (одного)  файла я разобрался с ней за 3 минуты. И без документации :D


Название: Re: Разбор QString
Отправлено: Old от Июль 03, 2013, 20:08
Мне трудно с бустом. К примеру те же самые рег экспы я не смог освоить в бусте за полчаса. Скачав библиотечку в виде 1 (одного)  файла я разобрался с ней за 3 минуты. И без документации :D
Попросите на работе проект без Qt, попробуйте все сделать на голом C++, уверяю вас, что по завершению проекта вы будете тут его восхвалять, так же как Qt. ;)

А уж скиллы как свои поднимите.... :)


Название: Re: Разбор QString
Отправлено: Bepec от Июль 03, 2013, 20:12
Спасибо, я саботировать работу не собираюсь ^.^


Название: Re: Разбор QString
Отправлено: Old от Июль 03, 2013, 20:14
Спасибо, я саботировать работу не собираюсь ^.^
В принципе да, для чего что-то еще, если есть Qt.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 03, 2013, 21:26
К сожалению "емкость мозга" ограничена - чем больше он набрался всякой всячины - тем более он беспомощен когда приходится думать/решать самому. Увы, по-видимому это неизбежно  :'(
Категорически с этим не согласен. Процесс осваивания и изучения чего то нового, как раз и развивает мышление, заставляет сопостовлять, находить, устанавливать связи и т.д.
Напротив, когда человек изолирован в решение своей задачи, очень может быть, что он просто окажется в тупике, бъясь лбом об стену.    


Название: Re: Разбор QString
Отправлено: Igors от Июль 04, 2013, 15:27
Тоже не правда. Любой программист C++ (внимание не С с классами), а грамотный программист, спокойно пользуется большинством бустовских библиотек.
Так это легко проверить. Вот Вы грамотный программист (ну или считаете себя таковым :)), спокойно пользуетесь бустом. И вот допустим возникла необходимость исправить то что сделал m_ax
Цитировать
(abc")de"fg)
В предыущей реализации m_ax на это забил, просто проверял парность скобок, поэтому первый токен будет (abc") что неверно. Думаю и в этой то же самое.

Сколько же Вам времени понадобится чтобы исправить? Подозреваю что "нисколько" - Вы за это просто не возьметесь - но будете продолжать говорить о "грамотности" и.т.п. Или я ошибаюсь и у Вас слова не расходятся с делом?  :)

Категорически с этим не согласен. Процесс осваивания и изучения чего то нового, как раз и развивает мышление, заставляет сопостовлять, находить, устанавливать связи и т.д.
В какой-то мере да, но это очень "однобоко", Вы в плену слишком абстрактных, схоластических конструкций. В реальных задачах фокус/центр тяжести часто совсем в др месте, а также неизвестно есть ли решение вообще. Ну вот напр давеча

- есть довольно популярная структура данных OcTree, найти реализацию и воспользоваться не составляет труда (возможно уже упоминал об этом здесь). Но вот беда - всего на 10K данных она сожрала 450 Mb. Может плохая реализация? Берем другую - хмм.. примерно то же самое. В чем дело? Или время поиска почему-то резко упало. У меня более 90% работы примерно такого плана, поэтому и отношусь прохладно у бусту, std - мне от них мало толку


Название: Re: Разбор QString
Отправлено: Old от Июль 04, 2013, 17:18
В предыущей реализации m_ax на это забил, просто проверял парность скобок, поэтому первый токен будет (abc") что неверно. Думаю и в этой то же самое.
Давайте четко сформулируем эти правила, а то "так по вашему верно, а так не верно", что бы вы в дальнейшем не вспоминали про исключения и "это и так должно быть понятным".
Для меня пока не понятно, а как будет правильно и какими символами мы вообще строку делим?


Название: Re: Разбор QString
Отправлено: Old от Июль 04, 2013, 20:08
Сколько же Вам времени понадобится чтобы исправить? Подозреваю что "нисколько" - Вы за это просто не возьметесь - но будете продолжать говорить о "грамотности" и.т.п. Или я ошибаюсь и у Вас слова не расходятся с делом?  :)
К сожалению m_ax не выложил всех исходников, поэтому исправить его вариант пока не могу.
Но я посмотрел на эту библиотеку и вот, что я набросал за 10 минут:
Код
C++ (Qt)
#include <iostream>
#include <boost/tokenizer.hpp>
 
using namespace boost;
 
template <class CharT>
class simple_char_separator
{
public:
       typedef std::basic_string<CharT> string_type;
       typedef typename string_type::const_iterator const_iterator;
 
       simple_char_separator() : m_open( "(" ), m_close( ")" ) {}
 
       void reset() {}
 
       bool operator()( const_iterator &next, const_iterator end, string_type &tok ) const
       {
               if( next == end )
           return false;
 
               const const_iterator start_pos = std::search( next, end, m_open.begin(), m_open.end() );
               if( start_pos == end )
                       return false;
 
               const const_iterator end_pos = std::search( start_pos, end, m_close.begin(), m_close.end() );
               tok.assign( start_pos, end_pos+1 );
 
               next = ( end_pos == end )? end : end_pos + 1;
 
       return true;
       }
 
private:
       std::string m_open;
       std::string m_close;
};
 
int main()
{
       std::string s = "(10, 20, 30) ( 10, 20, 30 ) (10, 20, 30)";
 
       std::cout << s << std::endl;
 
       tokenizer<simple_char_separator<char> > tok( s, simple_char_separator<char>() );
       for( auto v : tok )
       {
               std::cout << v << std::endl;
       }
 
  return 0;
}
 
Я так понял, что для вас Igors это недостижимый порог вхождения, а вот мнение Вереса, который писал о непонятках, интересно: скажите на сколько для вас это сложно и понимаете ли вы, что здесь делается?


Название: Re: Разбор QString
Отправлено: Bepec от Июль 04, 2013, 20:30
Вот вы написали интересный код.

Я его ни черта не понимаю. Что за токенизер что за симплечарсепаратор что за параметры ему передаются :)

Я смогу его использовать только после десятка неудачных применений :P Возможно это из-за моих знаний. (в идеале пара тестовых проектов)

Но как ни странно для меня идеал - это функция std::list<std::string> parse (std::string source, std::string separator). Потому что она ясна и понятна, что и как. И чтобы её использовать нет нужды писать магические слова. И мой коллега по работе поймёт эту функцию :D

PS с конструкцией auto я тоже незнаком, но уже нагуглил :D

PPS мой идеал - самодокументируемый понятный код. Но обычно получается самодокументируемая функция + парочка комментариев в ней.


Название: Re: Разбор QString
Отправлено: Old от Июль 04, 2013, 20:35
Я его ни черта не понимаю. Что за токенизер что за симплечарсепаратор что за параметры ему передаются :)
Информация по этому есть в посте m_ax.
А логика получения токенов там примитивная.

Но как ни странно для меня идеал - это функция std::list<std::string> parse (std::string source, std::string separator).
Вот ее замена в моем коде:
Код
C++ (Qt)
tokenizer<simple_char_separator<char> > tok( s, simple_char_separator<char>() );


Название: Re: Разбор QString
Отправлено: kambala от Июль 04, 2013, 20:36
код написан очень понятно, хотя я бустом пользовался всего раз в жизни (уже и не помню зачем) и шаблоны не особо люблю. надеюсь в документации по tokenizer так же понятно описывается как написать свой класс разбивателя.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 04, 2013, 20:40
Цитировать
В предыущей реализации m_ax на это забил, просто проверял парность скобок, поэтому первый токен будет (abc") что неверно. Думаю и в этой то же самое.
Я уже писал выше, почему считаю эту необходимость (в приорететах) избыточной.. Возможно корни таких решений растут от кривой архитектуры.
Во-вторых для моих целей приоритеты для цитат не требуются.

В-третьих, если мне всё же такой функционал и понадобится, то я, поверьте, его реализую.) Это не сложно)

Цитировать
К сожалению m_ax не выложил всех исходников, поэтому исправить его вариант пока не могу.

Я выкладывал)

Вот приаттачиваю простенький пример, чтоб можно было поиграться)

 


Название: Re: Разбор QString
Отправлено: Old от Июль 04, 2013, 20:52
Вот приаттачиваю простенький пример, чтоб можно было поиграться)
Ок, спасибо.
Но, вроде, мой примитивный набросок хорошо показывает необходимый порог вхождения. :)


Название: Re: Разбор QString
Отправлено: m_ax от Июль 04, 2013, 21:02
Вот приаттачиваю простенький пример, чтоб можно было поиграться)
Ок, спасибо.
Но, вроде, мой примитивный набросок хорошо показывает необходимый порог вхождения. :)


Согласен)

to Верес:
Цитировать
Но как ни странно для меня идеал - это функция std::list<std::string> parse (std::string source, std::string separator). Потому что она ясна и понятна, что и как. И чтобы её использовать нет нужды писать магические слова. И мой коллега по работе поймёт эту функцию Веселый
Хорошо, а теперь допустим, задача чуть усложнилась и Вам нужен другой алгоритм для разбиения строки на токены (например, что то подобное алгоритму offset_separator)..
Вы будете писать ещё один парсер для этого? 

А если нужна целая коллекция подобных алгоритмов? На каждый алгоритм свой парсер? Во что превратиться код?


Название: Re: Разбор QString
Отправлено: Bepec от Июль 04, 2013, 21:10
У меня на данный момент работают две функции на правилах + регэкспы. Всё необходимое задаётся в форме правил. Вполне понятно и просто.

PS ну и как мини аргумент - часто люди, использующие буст (я двух знаю) вместо "передавать файлы буста необходимые для сборки" требуют "скачайте буст и скопируйте по нашим путям". Очень увлекательное действие с 50 кб интернетом.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 04, 2013, 21:17
PS ну и как мини аргумент - часто люди, использующие буст (я двух знаю) вместо "передавать файлы буста необходимые для сборки" требуют "скачайте буст и скопируйте по нашим путям". Очень увлекательное действие с 50 кб интернетом.

А с Qt таких проблем не возникает, да)


Название: Re: Разбор QString
Отправлено: Bepec от Июль 04, 2013, 21:19
В организации, где Qt стоит у каждого на компе, ибо лицензия - да, не проблема. И дистрибутив хранится в каждом подразделении и на сервере :D  А вот буст как "левый" пакет программ пробросить в несколько физически разделённых сетей - это надо терпение :D


Название: Re: Разбор QString
Отправлено: Old от Июль 04, 2013, 21:59
Вот приаттачиваю простенький пример, чтоб можно было поиграться)
Я так понимаю, у вас этот код боевой?
Если да, то я бы добавил установку m_output_done в false в методе reset() spec_char_separator.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 04, 2013, 22:31
Вот приаттачиваю простенький пример, чтоб можно было поиграться)
Я так понимаю, у вас этот код боевой?
Если да, то я бы добавил установку m_output_done в false в методе reset() spec_char_separator.


Согласен)
Исправил.. Спасибо)


Название: Re: Разбор QString
Отправлено: Igors от Июль 05, 2013, 13:15
Давайте четко сформулируем эти правила, а то ...
Давайте, тот же пример
Цитировать
(abc ")de" fg)
Мы считаем токеном все что в круглых скобках (судя по Вашим ответам Вы это прекрасно поняли). Но по жизни кавычки экранируют все что в них (строка, литерал). Поэтому здесь должен быть 1 токен (вся исходная строка)

код написан очень понятно, хотя ...
Да, мне тоже все стало ясно за минуты. Хотя мне бы понадобилось не 10 а больше минут (разобраться куда что пристроить). Но этот код никак не делает того что просили, каычки ему пофиг.

Я уже писал выше, почему считаю эту необходимость (в приорететах) избыточной.. Возможно корни таких решений растут от кривой архитектуры.
Вы можете считать что угодно, но мы говорим о дальнейшей поддержке написанного Вами кода. Вот Вы написали, др люди этим пользуются, работает. Хирак - на этой строке (см выше) ошибка. А Вас нет - ушились гулять с собачкой  :)

Да, ну и не понял, в чем же величие буста (в данном случае)? Я так вижу что мы опять городим тот же самый велосипед, весь анализ баланса все равно на нас. С той лишь разницей что встроили его в бустовский функтор. Смысл? Так, попеть дифирамбы великому бусту, "приобщиться", пофорсить?  :)


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 13:31
Но этот код никак не делает того что просили, каычки ему пофиг.
Ну так добавьте. Я вам показал, как это элементарно делается в бусте и какой там порог вхождения/выхождения. :)

Вы можете считать что угодно, но мы говорим о дальнейшей поддержке написанного Вами кода. Вот Вы написали, др люди этим пользуются, работает. Хирак - на этой строке (см выше) ошибка. А Вас нет - ушились гулять с собачкой  :)
Точно-точно. Вы написали на Qt GUI и ушли гулять с собачкой, а тут хирак ошибка... Что делать, нужен человек знающий Qt.  ;D

Да, ну и не понял, в чем же величие буста (в данном случае)? Я так вижу что мы опять городим тот же самый велосипед, весь анализ баланса все равно на нас. С той лишь разницей что встроили его в бустовский функтор. Смысл? Так, попеть дифирамбы великому бусту, "приобщиться", пофорсить?  :)
А ваш парсер умеет парсить QByteArray или QLatin1String, а QVector или скажем std::vector? Нет?
Печально, а мой умеет и я ничего для этого не делал.



Название: Re: Разбор QString
Отправлено: m_ax от Июль 05, 2013, 14:16
Цитировать
Вы можете считать что угодно, но мы говорим о дальнейшей поддержке написанного Вами кода. Вот Вы написали, др люди этим пользуются, работает. Хирак - на этой строке (см выше) ошибка. А Вас нет - ушились гулять с собачкой  Улыбающийся
Опять это пугающее упоминание об "ошибке".. Алгоритм, которой я привёл чётко регламентирует область своего применения и соответствующие правила игры. Любой нормальный (адекватный) пользователь не будет пытаться использовать инструмент не по назначению. Если уж встанет необходимость в приорететах, то функционал может быть легко расширен.

Как это сделать: Old приводил пример выше, наглядно демонстрирующий как это можно реализовать.

Цитировать
Да, ну и не понял, в чем же величие буста (в данном случае)? Я так вижу что мы опять городим тот же самый велосипед, весь анализ баланса все равно на нас. С той лишь разницей что встроили его в бустовский функтор. Смысл? Так, попеть дифирамбы великому бусту, "приобщиться", пофорсить?

Если вы не видите очевидных преимуществ архитектурного решения boost::tokenizer, то дальнейшее обсуждение, боюсь, как всегда просто перейдёт во влуд..   
В чём преимущество Вашей архитектурной реализации? М?)


Название: Re: Разбор QString
Отправлено: Bepec от Июль 05, 2013, 14:36
Извините дяди, я опять вмешаюсь :)

Пользование бустом - хорошо.
Пользование отлаженным классом токенизер - хорошо.
Возможности этого класса - широки - хорошо.

То, что всем использующим этот код для "правки под себя"/"доработки" нужно будет знать буст - плохо.
То, что это решение не очевидно человеку, не пользующемуся бусту - плохо.
То, что код на деле несамодокументируемый - плохо.

Это различные точки мнения.

Кому то нужно взаимодействие с коллегами, кому то нет.

Кому то проще и быстрее написать свой велосипед под эту ситуацию (допустим с исключениями каких либо строк или сочетаний), чем подстраивать это решение под себя.

Кому то проще взять regexp и двумя регэкспами сделать всё то же самое.

PS не ссорьтесь :D

PPS и вообще парсинг строк - неблагодарное занятие :D


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 14:48
Это различные точки мнения.
Так никто и не навязывает... :)
Спор идет о том, что в качестве аргументов не применять буст используются субъективные страхи, которые выдаются за объективную реальность. :)


Название: Re: Разбор QString
Отправлено: Bepec от Июль 05, 2013, 14:49
Тогда сделайте решения и сравнивайте. А то так скоро во флуд тему.



Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 14:51
Тогда сделайте решения и сравнивайте. А то так скоро во флуд тему.
Я сомневаюсь, что решение Igors когда то будет уметь работать со всем, что имеет итераторы. :)
Точнее, тогда получиться решение из буста. :)


Название: Re: Разбор QString
Отправлено: Igors от Июль 05, 2013, 15:19
Алгоритм, которой я привёл чётко регламентирует область своего применения и соответствующие правила игры. Любой нормальный (адекватный) пользователь не будет пытаться использовать инструмент не по назначению.
Если человек хочет чтобы кавычки экранировали скобки - по-моему он совершенно нормальный :) А вот если реализация не обеспечивает такой возможности - это халтура, и неважно на дусте или на чем.

Как это сделать: Old приводил пример выше, наглядно демонстрирующий как это можно реализовать.
Не вижу никаких кавычек в приведенном примере, да и скобки почему-то hard-coded

Если вы не видите очевидных преимуществ архитектурного решения boost::tokenizer,
А Вам не кажется что Вы не задачу решаете, а расширяете свои познания? Эти вещи частенько мешают друг другу. Силенка ушла на вникание в хитросплетения темплейтов, а на реальные потребности пользователя - ничего не осталось. А когда пользователи или коллеги просят доделать - начинается виляние, ссылки на "архитектуру", "вы не понимаете" и.т.п. Таких знатоков/эрудитов лучше обходить стороной.

Точнее, тогда получиться решение из буста. :)
Ну как мы уже убедились - никакого готового решения (типа бери-пользуйся) для данного случая в бусте нет. Есть только уверения что, дескать, "это легко/элементарно добавить" - но почему-то реально показывается только парность скобок (да и то неправильная)


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 15:28
Не вижу никаких кавычек в приведенном примере, да и скобки почему-то hard-coded
Нуу, это ограничения языка, тут ничего нельзя поделать.  ;D

Таких знатоков/эрудитов лучше обходить стороной.
А заказчикам лучше обходить таких неумех программистов, которые за его деньги выдумывают велосипеды, вместо решения его задач.
Что будет если завтра, заказчик попросит сделать программу конвертации одно формата в другой без Qt (!) - вы напишите новый парсер? :)

Ну как мы уже убедились - никакого готового решения (типа бери-пользуйся) для данного случая в бусте нет. Есть только уверения что, дескать, "это легко/элементарно добавить" - но почему-то реально показывается только парность скобок (да и то неправильная)
Повторяю, это ограничения языка C++, тут ничего нельзя поделать. :)


Название: Re: Разбор QString
Отправлено: m_ax от Июль 05, 2013, 15:56
Цитировать
Если человек хочет чтобы кавычки экранировали скобки - по-моему он совершенно нормальный. А вот если реализация не обеспечивает такой возможности - это халтура, и неважно на дусте или на чем.
Я и не подвергаю сомнению нормальность человека, который хочет кавычки..
Ненормальный это тот, кто возмущается почему фотоаппаратом так неудобно открывать бутылки из под пива)

А почему ваша реализация не обеспечивает разбиение на токены по алгоритму подобному boost::offset_separator? Или, например я хочу выдерать токены заключённые в цитаты:
Код
C++ (Qt)
" (text1), бла бла бла {text2, text3}, ,, dsdfd (text4)"
 
 
хочу чтобы на выходе было:
Код
Bash
text1
text2, text3
text4
 
вы ведь не будете считать меня ненормальным из-за моих желаний? Почему же Вы не обеспечили в своём парсере такой возможности?
Это чистой воды - Халтура, Халтура с большой буквы Х)


Цитировать
А Вам не кажется что Вы не задачу решаете, а расширяете свои познания? Эти вещи частенько мешают друг другу. Силенка ушла на вникание в хитросплетения темплейтов, а на реальные потребности пользователя - ничего не осталось. А когда пользователи или коллеги просят доделать - начинается виляние, ссылки на "архитектуру", "вы не понимаете" и.т.п. Таких знатоков/эрудитов лучше обходить стороной.
Одно другому не мешает) Я решаю конкретную задачу и плюс ко всему расширяю свои познания) И это хорошо)
Никакого хитросплетения темплейтов я не вижу, вы как всегда драматизируете)
И да, как правильно заметил Old
Цитировать
А заказчикам лучше обходить таких неумех программистов, которые за его деньги выдумывают велосипеды, вместо решения его задач.





 


Название: Re: Разбор QString
Отправлено: Bepec от Июль 05, 2013, 16:26
И да, как правильно заметил Old

Не согласен. И по секрету скажу, что заказчику пофиг, как это будет сделано. Главное чтобы работало и не вылетало.

Когда я не был знаком с сериализацией, я сделал сохранение-загрузку данных тупо через файл строками. На это у меня ушло примерно минут 15.

Позже я сел и изучил s11n. На это у меня ушло примерно 4 дня.

Вот и посчитайте, господа "буст наше всё"/"нет велосипедам", разницу  между 15 минутами и 4 днями.  И мой велосипед есть и будет понятен всем с самым низким порогом. Отчасти из-за простоты, отчасти из-за комментариев.

PS скатились уже и в старый знакомый срач :/


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 17:08
Не согласен. И по секрету скажу, что заказчику пофиг, как это будет сделано. Главное чтобы работало и не вылетало.
Скажу по секрету, что заказчику нужно быстро, а поэтому разработчик должен уметь это сделать быстро.

Когда я не был знаком с сериализацией, я сделал сохранение-загрузку данных тупо через файл строками. На это у меня ушло примерно минут 15.
Если нужно сделать и дальше не трогать, то это действительно хорошо и просто, а вот если это в дальнейшем должно разрастись в огромную систему, то такой подход ошибочен. Будете переделывать все с нуля правильно.

И мой велосипед есть и будет понятен всем с самым низким порогом. Отчасти из-за простоты, отчасти из-за комментариев.
На самом деле бустовский код ясен и понятен. Там разделяется проход по строке и логика разбора, т.е. нам нужно менять только логику. Что правильно.

PS скатились уже и в старый знакомый срач :/
Как всегда. :)


Название: Re: Разбор QString
Отправлено: Igors от Июль 05, 2013, 21:00
А заказчикам лучше обходить таких неумех программистов, которые за его деньги выдумывают велосипеды, вместо решения его задач.
То да, но вот только кто здесь неумелый(е)? :) У меня-то все с любыми кавычками работает, а у Вас - только слова да понты.

А почему ваша реализация не обеспечивает разбиение на токены по алгоритму подобному boost::offset_separator? Или, например я хочу выдерать токены заключённые в цитаты:
(опускаю Ваш пример для краткости). Да пожалуйста, такая возможность в моем парсере есть, хотя запрос действительно "причудливый".

И да, как правильно заметил Old
Возможно Вам кажется что овладев очередным кусочком буста Вы сильно выросли :) Я думаю Вы наоборот, больше потеряли чем приобрели.

---------

Как верно заметил Верес, обсуждение скатилось в.. (ну неважно :)). Хорошо, а вот такая задачка

- было бы нехило если бы парсер умел выделять "числа". Примеры

5               // ну тут уже все выделено
10.2           // тут хужее, точка может юзаться и по-другому
3.45f          // увы, это возможно
1.2e-5        // и это надо поддерживать
2.3e+10f    // и это

При этом, разумеется, весь имеющийся ф-ционал (цитаты и.т.п) должен быть сохранен. Какие есть мнения?


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 21:09
У меня-то все с любыми кавычками работает
С чего это они работают? Даже не компилируется:
Код
C++ (Qt)
// std::string str("1, { 2 }, 3");    // ни так
QByteArray str("1, { 2 }, 3");      // ни даже так
QStringRef ref;
QStringParser parser(str, param);
while (parser.NextToken(ref))
qDebug() << ref.toString();
 
Как правильно написал m_ax - Халтура.

а у Вас - только слова да понты.
А у меня не оплачено. :(
Помните: "Ни строчки кода без бабосов" и "Я никому помогать просто так не буду"? ;)

А если серьезно, то вы говорили про сложный вход, я привел вам пример, как это просто, вы даже согласились. Все что я хотел донести я донес.


Название: Re: Разбор QString
Отправлено: Igors от Июль 05, 2013, 21:24
С чего это они работают? Даже не компилируется:
Код
C++ (Qt)
// std::string str("1, { 2 }, 3");    // ни так
QByteArray str("1, { 2 }, 3");      // ни даже так
 
Вы посмотрите название темы - а играться в "общность" будете в др месте  :)

А у меня не оплачено. :(
Помните: "Ни строчки кода без бабосов" и "Я никому помогать просто так не буду"? ;)
Пока я в упор не вижу за что Вам платить - скорее наоборот  :)

А если серьезно, то вы говорили про сложный вход, я привел вам пример, как это просто, вы даже согласились. Все что я хотел донести я донес.
Ну так если серьезно - я в упор не вижу на хрена мне здесь буст, все равно все делать руками, так зачем еще зависеть от посторонки?


Название: Re: Разбор QString
Отправлено: Old от Июль 05, 2013, 21:43
Вы посмотрите название темы - а играться в "общность" будете в др месте  Улыбающийся
Вы знаете, точнее - вы не знаете, что общность можно сделать и на Qt.
Я привел классы, которые было бы удобно поддерживать. Первый это QByteArray - это тот контейнер, в котором мы получаем данные из вне, ну и QLatin1String почему-то забыт. Если вы ими не пользуетесь, то это не значит, что ими не пользуются другие.

Пока я в упор не вижу за что Вам платить - скорее наоборот  :)
Я тоже не вижу за что вам платить, но это не мешает вам находить несчастных.... ;)

Ну так если серьезно - я в упор не вижу на хрена мне здесь буст, все равно все делать руками, так зачем еще зависеть от посторонки?
Основная проблема диалога с вами заключается в том, что вы или не читаете (забываете?), или не понимаете собеседника.
Вам никто не предлагает использовать буст! Всем совершенно все равно что вы тут использовали или не использовали.
m_ax решил поделиться со всеми тем, что по его мнению, подход (концепция) решения этой задачи в бусте более общий (универсальный). Вы начали защищать (непонятно для чего?) свое решение и придумывать кучу причин и басен про буст. Я начал с вами спорить про "сложности" буста (и мозг :) ), вы попросили доказательств, я их привел, вы согласились. Все.
Попробуйте это понять. :)
Или, знаете что, не надо понимать: если ваш мозг работает как вы описали, то я переживаю о его overflow. ;)



Название: Re: Разбор QString
Отправлено: Igors от Июль 06, 2013, 08:46
... подход (концепция) решения этой задачи ...
А я вот не уверен что концепция так уж хороша (с бустом или без).

Сейчас "на гора" выдаются токены и подразумевается что клиент знает что дальше с ними делать. Это неизбежно, но не слишком ли низкоуровневый выход получается, не долговато ли клиент будет разбираться "а что это?"  Не ввести ли типы (как поле структуры токена)? Напр
Код
C++ (Qt)
enum {
type_String,     // строка, клиент разбирается сам
type_Quote,     // цитата, известно какая
type_Number,  // число (см выше в теме)
type_EOL,       // конец строки
type_Char,      // символ, клиент разбирается сам
};
 


Название: Re: Разбор QString
Отправлено: Old от Июль 06, 2013, 09:03
А я вот не уверен что концепция так уж хороша (с бустом или без).
Буст предлагает самое низкоуровневое (универсальное) решение, а вы, например, можете сделать на его основе "среднее" (как вы сейчас предложили). А конечный пользователь (и вы в том числе), на основе "среднего" сможете делать конечные парсеры на любой вкус и кошелек.

type_Quote,     // цитата, известно какая
Что значит известно какая? Это "..." или '...' или `...` или `...' (и такие есть)?
И что она будет означать? Если клиенту нужны токены (...), а на входе: (13123 ")24324" 345345), что будет возвращено - цитата или строка?


Название: Re: Разбор QString
Отправлено: Old от Июль 06, 2013, 09:29
10.2           // тут хужее, точка может юзаться и по-другому
3.45f          // увы, это возможно
1.2e-5        // и это надо поддерживать
2.3e+10f    // и это
Если точка может быть разделителем токенов, то никак.


Название: Re: Разбор QString
Отправлено: Igors от Июль 06, 2013, 09:42
Что значит известно какая?
Пример: парсер вернул токен
Цитировать
(a + b)
Это правильно, т.к. клиенту нужно "все что в скобках" + знать что "это в круглых скобках". Однако получив токен клиент вероятно будет пытаться выяснить "а цитата ли это" и "какая". Это явно неэффективно т.к. парсер только что это уже сделал - так пусть он и запишет ее ID чтоб потом не бегать.

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


Название: Re: Разбор QString
Отправлено: Old от Июль 06, 2013, 09:48
Это правильно, т.к. клиенту нужно "все что в скобках" + знать что "это в круглых скобках". Однако получив токен клиент вероятно будет пытаться выяснить "а цитата ли это" и "какая". Это явно неэффективно т.к. парсер только что это уже сделал - так пусть он и запишет ее ID чтоб потом не бегать.
А цитат может быть много: (...) {...} "..." '...' и т.д.
Какой будет ID? А пользователю придется выяснять все равно, что это за цитата.

Ну чего же, пробежаться вперед никто не запрещает
Пробегитесь: 1.4.5.6.12.55.66f.123
Сколько здесь чисел и какие?


Название: Re: Разбор QString
Отправлено: Igors от Июль 06, 2013, 11:24
А цитат может быть много: (...) {...} "..." '...' и т.д.
Какой будет ID? А пользователю придется выяснять все равно, что это за цитата.
Конечно придется, но куда меньшими затратами

Пробегитесь: 1.4.5.6.12.55.66f.123
Сколько здесь чисел и какие?
Здесь ни одного числа, это один токен - строка, а вот напр так
Цитировать
1.4  5.6.12.55.66f.123
2 токена, number и string.

Edit: виноват, не один и не строка - серия токенов строка + символ (если точка юзается). Но суть та же - клиенту трудно "без контекста" - он будет вынужден привлекать пред/пост историю. Разумно переложить это на базовый парсер.


Название: Re: Разбор QString
Отправлено: m_ax от Июль 07, 2013, 15:49
А цитат может быть много: (...) {...} "..." '...' и т.д.
Какой будет ID? А пользователю придется выяснять все равно, что это за цитата.
Конечно придется, но куда меньшими затратами

Меньшими чем что?
Ну хорошо, предположим, понадобилась вам такая функциональность (можно понять).. И что, будете добавлять в интерфейс своего парсера дополнительные методы, возвращающие доп. информацию о текущем токене? В любом случае, архитектура вашего string parser'а будет требовать (завязана) информацию о классе, предоставляющем её (доп. информацию).

А теперь, (внезапно) вам понадобилось расширить возможности Вашего парсера.. Опять будете чего то добавлять в него? Писать доп. классы и т.д?
Этот процесс, при использованной Вами архитектуре, может вообще не закончится,  плодя различного рода зависимости между парсером и конкретными алгоритмами разбиения строки на токены.
И от этого, при данном подходе, не избавиться, как от крошек на кровати(

В то время, как решение boost::tokenizer позволяет и для такого случая (с доп. информацией) отдельно локализовать логику и интерфейс.

 
     


Название: Re: Разбор QString
Отправлено: Igors от Июль 08, 2013, 11:09
Первая архитектура которая приходит в голову

- вот пусть данный парсер порубит на токены, которые будут сложены в контейнер. А дальше уже др обработчик/класс этим контейнером займется, учитывая специфику приложения.

Здесь привлекает то что никаких зависимостей не создается. В общем, из этих соображений и был написан этот парсер. Однако сейчас (год спустя) мне не кажется что это "так уж хорошо". Особенно если исходная QString содержит много текстовых строк (разделенных EOL)

Какие есть мненмя?


Название: Re: Разбор QString
Отправлено: m_ax от Июль 08, 2013, 11:49
Первая архитектура которая приходит в голову

- вот пусть данный парсер порубит на токены, которые будут сложены в контейнер. А дальше уже др обработчик/класс этим контейнером займется, учитывая специфику приложения.

Здесь привлекает то что никаких зависимостей не создается. В общем, из этих соображений и был написан этот парсер. Однако сейчас (год спустя) мне не кажется что это "так уж хорошо". Особенно если исходная QString содержит много текстовых строк (разделенных EOL)

Какие есть мненмя?

если уж очень нужна доп. информация о токенах, то в подходе bоost::tokenizer я бы передавал (возможно опционально) в конструктор user_token_separator ссылку или указатель на объект token_details в которой уже на каждой итерации записывал необходимую информацию.

Код
C++ (Qt)
token_details details;
boost::tokenizer<user_token_separator> tok(str, user_token_separator(details));
for (auto s : tok) {
   if (details.is_quote) {...}
   //или да, записывать токены и соответствующую инфу о нём в некий контейнер.
 
}
 

Кода писал bib парсер я тоже записывал промежуточные токены в контэйнер и далее уже работал с ним.


Название: Re: Разбор QString
Отправлено: Igors от Июль 09, 2013, 15:22
Кода писал bib парсер я тоже записывал промежуточные токены в контэйнер и далее уже работал с ним.
Возникает суета с концами строк
Цитировать
// anything followed up to the line should ne ignored: " ' ( [ etc.
Уложить это в "цитату" не удается т.к. может быть 3 варианта EOL. Др случай
Цитировать
poly
...
...
face
Да, я знаю что есть "poly" но не умею или не хочу его разбирать - мне нужно пропускать все до тех пор пока строка не начнется с чего-то значащего для меня (напр "face")

В конце-концов просто найти "конец строки" сейчас тоже неудобно. Выходит так:
- если токен \n и следующий \r - это EOL Windows 
- если токен \n - это EOL Unix 
- если токен \r - это EOL Mac (старые файлы), но надо иметь ввиду предыдущий

Да, все это можно сделать "сначала собрав все токены" но это громоздко. Возможно что произошла ошибка или недопустимая ситуация уже вначале, но мы не можем ничего поделать "не собрав все токены". А если парсить "строка за строкой" - тогда получаем незакрытые цитаты.   


Название: Re: Разбор QString
Отправлено: m_ax от Июль 09, 2013, 23:16
Я загружаю в буфер сразу весь файл,
с помощью регулярки нахожу необходимый мне блок. Далее, в его пределах использую всякие токенайзеры в зависимости от конкретной задачи.

Могу в качестве примера bib_parser приаттачить..