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

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

Страниц: 1 2 3 [4] 5 6 ... 8   Вниз
  Печать  
Автор Тема: Парсинг строки определенного типа  (Прочитано 48639 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #45 : Май 05, 2014, 17:30 »

"Из пушки по воробьям" ©
Вы сейчас о чем? О регулярках?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #46 : Май 05, 2014, 17:35 »

как правило регулярки не использует и ругает тот, кто в них не разобрался Улыбающийся не так часто бывают случаи где надо выжимать максимальную скорость (счет на миллисекунды).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Bepec
Гость
« Ответ #47 : Май 05, 2014, 17:55 »

Они удобны для заковыристых и масштабных случаев. Когда же формат простой они просто не нужны... (моё мнение ^.^)

К тому же тут имеется факт что поддержка дальнейшая должна тоже знать reg exp'ы.

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

Но спорить бессмысленно, это уже вопрос к ТСсу - что ему надо Улыбающийся
Записан
k0p4
Гость
« Ответ #48 : Май 05, 2014, 18:10 »

Цитировать
А почему они не корректные? Табуляция такой же символ разделитель как и пробел.
Да, верно. А еще у меня в файлике может быть такой сплиттер "My\npretty$splitter\t\r\n\r\n;amp&". Формат сплиттеров в фале обговаривается стандартом для данного файлика. Иначе представляю как парсились бы пресловутые плэйлисты.

Цитировать
Вот-вот. На каждый чих. А потому так в этом погрязните, что сами ничего не сможете разобрать.
В коде парсера, который парсит заданный формат файла, тяжело не разобратся. Я так пологаю, что даже студены с простыми фаиндами совладают.
 
Цитировать
Это пока все так легко и просто. А теперь представьте, что выдернуть нужно не цифры, а номер телефон и email. Проверить их на валидность и выдернуть.
Здесь вам надо привести алгоритм? Это просто.

Цитировать
А так можно принять что в файле позиции чисел фиксированы:
-Y 00012 +X 01234
И выдергивать их из строку по точным смещениям: первое число - подстрока 3-7 символ; второе число - подстрока 11-15.
Ну а что, будет еще быстрей.
Это самый лучший способ. Но смещений не будет. Т.е. не будет дополнительных нулей.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #49 : Май 05, 2014, 18:19 »

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

Здесь вам надо привести алгоритм? Это просто.
Мне алгоритм не нужен, добавьте к своему парсеру такую возможность.
Например теперь формат такой:
-Y 10     +X    204           \t\t Phone +7-909-909-99-99      EMail progorg@prog.org.ru

Номер телефона может быть с +7, может с 8, а может вообще без этого префикса. Попробуйте телефон с электронкой проверять на валидность. Подмигивающий А с регулярками это одна строка, которая их еще и выделит.
Записан
k0p4
Гость
« Ответ #50 : Май 05, 2014, 18:45 »

Цитировать
Мне алгоритм не нужен
Цитировать
добавьте к своему парсеру такую возможность

Так всё-таки не нужен или добавить?

Цитировать
Попробуйте телефон с электронкой проверять на валидность.
А это уже другая задача, которую действительно лучше решить регуляркой (я про валидацию мыла и телефона). Валидация выдраных данных - это отдельный функционал. Речь шла о парсе.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #51 : Май 05, 2014, 18:56 »

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

Записан
k0p4
Гость
« Ответ #52 : Май 05, 2014, 19:01 »

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



В общем и целом - Вы правы. Но с другой стороны ни разу в своих проектах не пользовал регулярку. Тем более, что парсить приходилось либо ini-подобные файлы, либо JSON, либо XML. Я плохой программист, что не использовал регулярки для парса ini-подобных файлов?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #53 : Май 05, 2014, 19:13 »

Я плохой программист, что не использовал регулярки для парса ini-подобных файлов?
Ну это просто детский сад. Улыбающийся
Вовсе нет.
Записан
_OLEGator_
Гость
« Ответ #54 : Май 05, 2014, 20:25 »

Они удобны для заковыристых и масштабных случаев. Когда же формат простой они просто не нужны... (моё мнение ^.^)

К тому же тут имеется факт что поддержка дальнейшая должна тоже знать reg exp'ы.

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

Но спорить бессмысленно, это уже вопрос к ТСсу - что ему надо Улыбающийся

О чем спор?
Если программист ноет о том, что ему сложно разобраться в регулярных выражениях - грош цена такому программисту, не ту профессию он выбрал.
Программист должен постоянно развиваться и использовать не только базовые возможности языка, застяв в if'ах.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #55 : Май 05, 2014, 21:08 »

Во-первых, код приведённый k0p4ем весьма наивен..

Давайте взглянем на всё это более трезво.. (хотя я сейчас и после юбилея своей бабушки, но всё же)

И так, мы хотим распарсить некий, достаточно детский формат данных.. Причём, так, что бы мы имели информацию о том, что пошло не так..
Если, например, в какой то строке что то не соответствует правилам игры, то код  k0p4а просто пролетает..

Вот вариант того (народный метод в лоб), что мне сейчас удалось написать на коленке:
Код
C++ (Qt)
#include <QString>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QVector>
#include <QPoint>
#include <QRegExp>
#include <QList>
 
bool extractData(const QString & str, int & x, int & y)
{
   static const QString prefixX = "+X";
   static const QString prefixY = "-Y";
   static const QChar space = ' ';
 
 
   if (!str.startsWith(prefixY))
   {
       qDebug() << "1 ;(";
       return false;
   }
 
   int n = prefixY.size();
   if (str[n] != space)
   {
       qDebug() << "2 ;(";
       return false;
   }
 
   if (++n == str.size())
   {
       qDebug() << "3 ;(";
       return false;
   }
 
   int m = str.indexOf(space, n);
   if (m == -1)
   {
       qDebug() << "4 ;(";
       return false;
   }
 
   bool ok = false;
   y = str.mid(n, m-n).toInt(&ok);
   if (!ok)
   {
       qDebug() << "5 ;(";
       return false;
   }
 
   if (str[m] != space)
   {
       qDebug() << "6 ;(";
       return false;
   }
 
   n = str.indexOf(prefixX, ++m);
 
   if (n != m)
   {
       qDebug() << "7 ;(";
       return false;
   }
 
   n += prefixX.size();
 
   if (n == str.size())
   {
       qDebug() << "8 ;(";
       return false;
   }
 
   x = str.mid(++n, str.size()).toInt(&ok);
 
   if (!ok)
   {
       qDebug() << "9 ;(";
       return false;
   }
 
   return true;
 
}
 
Это тот "простейший метод" сделать  это прогоняясь по строке. Обратите внимание на число проверок (необходимых), для того, что бы в итоге не получить полную чушь.

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

Во-вторых, все эти вопли о производительности здесь лишены смысла.. Да, в данном случае, решение в лоб, работает быстрее.. Но.. Но не более чем в три раза.. Это даже не порядок величины! Стоит ли ради этого городить весь этот костыльный вариант?
Вот как выглядит решение с QRegExp^
Код
C++ (Qt)
template <class Container>
void readData_QRegExManner(const QString & fileName, Container & v)
{
   QFile file(fileName);
   if (!file.open(QIODevice::ReadOnly))
   {
       qDebug() << "Error opening file";
       return;
   }
 
   QTextStream stream(&file);
 
   QString str = stream.readAll();
 
   QRegExp regex("\\-Y (\\d+) \\+X (\\d+)");
   regex.setMinimal(true);
 
   int pos = 0;
   while ((pos = regex.indexIn(str, pos)) != -1)
   {
       int y = regex.cap(1).toInt();
       int x = regex.cap(2).toInt();
       v.append(QPoint(x, y));
       pos += regex.matchedLength();
   }
 
 
}
 
Всё! Это решение гораздо более устойчивее к начальным условиям. Потребуется добавить что то сверх формата, то в RegExp это делается заменой только одной строки.. А что будет в "народном"варианте в лоб? Код как минимум увеличится в разы..
И не говорите мне, что сопровождать эту кашу будет легче..  Напротив(

И в-третьих, если уж вы так вопите о производительности, то банальный boost::xpressive сделает всех..
А если кто то так заботиться о обработке ошибок и т.п.. то boost::spirit предоставляет гибкие решения и этой проблемы.
Оставаясь на порядок более гибким, понятным и производительным решением..)

Лично с моей точки зрения, решение"построчного пробега" - это последнее, что пришло бы мне в голову( В общем случаее и в частности..  


« Последнее редактирование: Май 05, 2014, 21:10 от m_ax » Записан

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

Arch Linux Plasma 5
Bepec
Гость
« Ответ #56 : Май 05, 2014, 22:30 »

to _OLEGator_: Один раз мы переписывали программу из-за того, что все программисты "поддержки" в фирме умели программировать только на... паскале. Какие там рег экспы Улыбающийся
Суть сообщения которую я хочу до вас донести - высокие стандарты это гуд, развиваться надо, но остались ещё люди, пишушие x= x+1; x=x+2; x=x+3; x=x+n вместо цикла Улыбающийся

PS ну и читабельность кода. Мб у меня мало опыта, но представить по регулярке исходное выражение я не могу, особенно если группы используются.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #57 : Май 05, 2014, 23:33 »

to _OLEGator_: Один раз мы переписывали программу из-за того, что все программисты "поддержки" в фирме умели программировать только на... паскале. Какие там рег экспы Улыбающийся
Суть сообщения которую я хочу до вас донести - высокие стандарты это гуд, развиваться надо, но остались ещё люди, пишушие x= x+1; x=x+2; x=x+3; x=x+n вместо цикла Улыбающийся

PS ну и читабельность кода. Мб у меня мало опыта, но представить по регулярке исходное выражение я не могу, особенно если группы используются.

Угу.. Вот это то и печально( Печально, когда код пишется для таких "профессианалов" которые только на паскале и умеют..
И то, что остались ещё люди, пишущие x = x + 1 и т.п. никак не оправдывает вашу политику фирмы.. А напротив(
А в итоге имеем дегродированный код, который если что, то лучше переписать с нуля, чем поддерживать в дальнейшем( 
Записан

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

Arch Linux Plasma 5
Bepec
Гость
« Ответ #58 : Май 05, 2014, 23:43 »

Ммм... зато после ядрёной войны этот код сможет восстановить и поправить и поддержать любой самоучка с книжкой по С++ Улыбающийся Так что во всём свои плюсы.

PS я не вижу "где плохо". Простота формата = простоте кода = простота поддержки. Я вижу будущее за понятным кодом, аналогом Qt. Где со строкой мы работаем как со строкой, а не копируем области памяти в области памяти и представляем всё массивом.

PPS да, заглядывая во внутренности Qt, я не увидел там шаблонов, страшных конструкций и прочего. Всё просто. Назовёте код Qt плохим?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #59 : Май 05, 2014, 23:49 »

Ммм... зато после ядрёной войны этот код сможет восстановить и поправить и поддержать любой самоучка с книжкой по С++ Улыбающийся Так что во всём свои плюсы.

PS я не вижу "где плохо". Простота формата = простоте кода = простота поддержки. Я вижу будущее за понятным кодом, аналогом Qt. Где со строкой мы работаем как со строкой, а не копируем области памяти в области памяти и представляем всё массивом.

PPS да, заглядывая во внутренности Qt, я не увидел там шаблонов, страшных конструкций и прочего. Всё просто. Назовёте код Qt плохим?
Т.е. я правильно понял, что для вас этот код:
Код
C++ (Qt)
bool extractData(const QString & str, int & x, int & y)
{
   static const QString prefixX = "+X";
   static const QString prefixY = "-Y";
   static const QChar space = ' ';
 
 
   if (!str.startsWith(prefixY))
   {
       qDebug() << "1 ;(";
       return false;
   }
 
   int n = prefixY.size();
   if (str[n] != space)
   {
       qDebug() << "2 ;(";
       return false;
   }
 
   if (++n == str.size())
   {
       qDebug() << "3 ;(";
       return false;
   }
 
   int m = str.indexOf(space, n);
   if (m == -1)
   {
       qDebug() << "4 ;(";
       return false;
   }
 
   bool ok = false;
   y = str.mid(n, m-n).toInt(&ok);
   if (!ok)
   {
       qDebug() << "5 ;(";
       return false;
   }
 
   if (str[m] != space)
   {
       qDebug() << "6 ;(";
       return false;
   }
 
   n = str.indexOf(prefixX, ++m);
 
   if (n != m)
   {
       qDebug() << "7 ;(";
       return false;
   }
 
   n += prefixX.size();
 
   if (n == str.size())
   {
       qDebug() << "8 ;(";
       return false;
   }
 
   x = str.mid(++n, str.size()).toInt(&ok);
 
   if (!ok)
   {
       qDebug() << "9 ;(";
       return false;
   }
 
   return true;
 
}
 
более предпочтительнее для дальнейшей поддержки?
Не смотря на те аргументы, что я показал всю костыльность этого подхода?

Ну тогда у меня вопросов больше нет(

И кстатии, вы уверены, что после ядерной войны кому то вообще придёт в голову восстанавливать этот бред?
Хотя, конечно, ничего другого, кроме говнокода (и ремесленников средней руки), после ядерной войны не останется..
« Последнее редактирование: Май 06, 2014, 00:20 от m_ax » Записан

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

Arch Linux Plasma 5
Страниц: 1 2 3 [4] 5 6 ... 8   Вверх
  Печать  
 
Перейти в:  


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