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

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

Голосование
Вопрос: Хотите ли Вы в этом разбираться?
Да, хочу - 4 (22.2%)
Было бы полезно, но нет времени - 5 (27.8%)
Нет, это не окупает изучения - 4 (22.2%)
Та ну его нафиг! - 5 (27.8%)
Ваш вариант - 0 (0%)
Всего голосов: 11

Страниц: [1] 2 3 ... 8   Вниз
  Печать  
Автор Тема: Хотите ли Вы в этом разбираться?  (Прочитано 48611 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Апрель 21, 2014, 19:55 »

Добрый день

Оригинал здесь http://www.prog.org.ru/topic_26887_0.html. Для удобства содержательная часть (как я ее понял) ниже

Мне нужно распарсить некоторый текст, формат которого предполагает наличие комментариев. Комментарий начинается с определённого символа и заканчивается другим.
 ..
Вот маленький пример: символ начала коммента - %, конец коммента - \n):
Код
C++ (Qt)
#include <iostream>
#include <boost/regex.hpp>
#include <string>
#include <list>
#include <boost/range/istream_range.hpp>
#include <algorithm>
 
template <class T = char>
class tex_string_iterator : public std::iterator<std::bidirectional_iterator_tag, T, ptrdiff_t, const T*, const T&>
{
public:
   typedef T char_type;
   typedef std::basic_string<T> string_type;
   typedef typename std::basic_string<T>::const_iterator string_iterator;
 
   tex_string_iterator(string_iterator begin, string_iterator end, T bra = '%', T ket = '\n')
       : _begin(begin), _end(end), _it(begin), _bra(bra), _ket(ket)
   {
       make_comments_list();
   }
 
   tex_string_iterator(const tex_string_iterator<T>& iter)
       : _begin(iter._begin), _end(iter._end), _it(iter._it),
         _bra(iter._bra), _ket(iter._ket), _comments_list(iter._comments_list) {}
 
   tex_string_iterator<T>& operator=(const tex_string_iterator & iter) {
       if (this != &iter) {
           _begin = iter._begin;
           _end = iter._end;
           _it = iter._it;
           _bra = iter._bra;
           _ket = iter._ket;
           _comments_list = iter._comments_list;
       }
       return *this;
   }
 
   tex_string_iterator() {}
 
   ~tex_string_iterator() {}
 
   const T& operator*() const { return *_it; }
 
   const T* operator->() const { return _it; }
 
   tex_string_iterator<T>& operator++() {
 
       if (*_it != _bra) {
           if (++_it == _end)
               return *this;
           if (*_it != _bra)
               return *this;
       }
 
       for (const auto & comment : _comments_list) {
           if (comment.begin() == _it) {
               _it = comment.end();
               if (_it == _end)
                   break;
 
               if (*(++_it) != _bra)
                   break;
           }
       }
 
       return *this;
   }
 
   tex_string_iterator<T> operator++(int) {
       tex_string_iterator<T> tmp = *this;
       ++*this;
       return tmp;
   }
 
   tex_string_iterator<T>& operator--() {
 
       if (*_it != _ket) {
           --_it;
           if (*_it != _ket)
               return *this;
       }
 
       for (const auto & comment :_comments_list) {
           if (comment.end() == _it) {
               _it = comment.begin();
               if (_it == _begin)
                   break;
 
               if (*(--_it) != _ket)
                   break;
           }
       }
 
       return *this;
   }
 
   tex_string_iterator<T> operator--(int) {
       tex_string_iterator<T> tmp = *this;
       --*this;
       return tmp;
   }
 
   template <class R>
   friend bool operator==(const tex_string_iterator<R> &, const tex_string_iterator<R> &);
 
   template <class R>
   friend bool operator!=(const tex_string_iterator<R> &, const tex_string_iterator<R> &);
 
private:
   string_iterator _begin;
   string_iterator _end;
   string_iterator _it;    //current iterator
   T _bra;                 //open comment symbol
   T _ket;                 //closed comment symbol
   std::list<boost::iterator_range<string_iterator>> _comments_list;
 
   void make_comments_list() {
       if (_begin == _end)
           return;
 
       auto first = _begin;
       auto second = _begin;
 
       while ((first = std::find(first, _end, _bra)) != _end) {
           second =  std::find(first, _end, _ket);
           _comments_list.push_back(boost::iterator_range<string_iterator>(first, second));
           first = second;
       }
   }
};
 
template<class T>
inline bool operator==(const tex_string_iterator<T> & x, const tex_string_iterator<T> & y) {
   return (x._it == y._it);
}
 
template<class T>
inline bool operator!=(const tex_string_iterator<T> & x, const tex_string_iterator<T> & y) {
   return !(x == y);
}
 
int main()
{
 
   std::string buffer = "text text %comment comment\n text nocomment";
 
   tex_string_iterator<char> ibegin(buffer.begin(), buffer.end(), '%', '\n');
   tex_string_iterator<char> iend(buffer.end(), buffer.end());
 
   boost::regex_iterator<tex_string_iterator<char>> it(ibegin, iend, boost::regex("(com)"));
   boost::regex_iterator<tex_string_iterator<char>> end;
   for (; it != end; ++it) {
       std::cout << it->str(1) << std::endl;
   }
 
  return 0;
}
 

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

Сообщений: 4349



Просмотр профиля
« Ответ #1 : Апрель 21, 2014, 19:59 »

Хорошее голосование.  Смеющийся
Хотите ли вы разбираться в C++?
На форуме домохозяек вы бы произвели фурор таким голосованием.

Хотите избавится от комплекса неосилятора? Не поможет. Подмигивающий
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Апрель 21, 2014, 20:12 »

Хорошее голосование.  Смеющийся
Хотите ли вы разбираться в C++?
На форуме домохозяек вы бы произвели фурор таким голосованием.

Хотите избавится от комплекса неосилятора? Не поможет. Подмигивающий
Ох и злобный дустовец попался  Улыбающийся Мое мнение "3", я считаю что владение задрочеными обобщенными конструкциями имеет к знанию языка очень косвенное отношение. Все-таки С/С++ никогда не обладал гибкостью интерпретатора (что нормально, недостатки = продолжение достоинств). И попытки насилия над языком есть извращение (не спорю - интересное  Улыбающийся)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #3 : Апрель 21, 2014, 20:20 »

я считаю что владение задрочеными обобщенными конструкциями имеет к знанию языка очень косвенное отношение. Все-таки С/С++ никогда не обладал гибкостью интерпретатора
Как по вашему обобщенные конструкции соотносятся с интерпретаторами?  Строит глазки
Никакого "насилия над языком" нет, это ваши фантазии. Все что вам не удалось осилить из языка, вы считаете задроченым и не нужным.
К нашей радости вы хотя бы контейнеры осилили и QString, а то бы сейчас нам рассказывали как они ненужны.  Смеющийся
Записан
OKTA
Гость
« Ответ #4 : Апрель 22, 2014, 00:01 »

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

Я еще далеко не профессионал, но знаю, что профессиональный код пишется "для дебилов". Не раз заглядывал в код, который пишется для архи-сложных систем и там все просто, как два байта переслать  Смеющийся А тут застрелиться желание возникает, нежели разобраться, как и что работает)))))
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #5 : Апрель 22, 2014, 00:18 »

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

Я еще далеко не профессионал, но знаю, что профессиональный код пишется "для дебилов". Не раз заглядывал в код, который пишется для архи-сложных систем и там все просто, как два байта переслать  Смеющийся А тут застрелиться желание возникает, нежели разобраться, как и что работает)))))

Хотите способ, как лишить девственности Ваши наивные представления о профессиональном коде и решениях?   
Полистайте перед сном  исходники boost'а, особенно boost::spirit
Возможно, после этого ваше мнение измениться..  Улыбающийся

А вообще, дело даже не в конкретной реализации.. Вам не нужно знать что скрыто под капотом.. Важно архитектурные решения, сами подходы к решению проблем.. Гибкость и расширяемость.
Вот igors не разобравшись с проблемой, полез в копания каких то не существенных деталей.. частностей..  А Вы ведётесь на это(   
Записан

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

Arch Linux Plasma 5
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #6 : Апрель 22, 2014, 01:03 »

владение задрочеными обобщенными конструкциями имеет к знанию языка очень косвенное отношение
А какие именно конструкции в приведенном выше примере "задроченные/обобщенные"?

Вроде код читается относительно не сложно. Но по нескольким моментам возникают вопросы:
  • зачем переопределять конструкор копии и оператор присваивания, чем сгенерированные по умолчанию не подходят?
  • зачем жестко привязываться к std::basic_string, вроде бы такая обертка возможна для любого bidirectional итератора?
  • почему бы не отслеживать текущий элемент в _comments_list и не делать линейный поиск в ++/-- ?
  • почему в == не сравниваются begin/end?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #7 : Апрель 22, 2014, 07:54 »

владение задрочеными обобщенными конструкциями имеет к знанию языка очень косвенное отношение
А какие именно конструкции в приведенном выше примере "задроченные/обобщенные"?

Вроде код читается относительно не сложно. Но по нескольким моментам возникают вопросы:
  • зачем переопределять конструкор копии и оператор присваивания, чем сгенерированные по умолчанию не подходят?
  • зачем жестко привязываться к std::basic_string, вроде бы такая обертка возможна для любого bidirectional итератора?
  • почему бы не отслеживать текущий элемент в _comments_list и не делать линейный поиск в ++/-- ?
  • почему в == не сравниваются begin/end?

Согласен, необходимости в коп.конструкторе и операторе присваивания сейчас нет)

Да, к std::basic_string тоже не обязательно привязываться (не хотел пугать igors'са ещё одним шаблоном  Улыбающийся )

3) Таки да, вчера как раз это исправил (но можно сделать ещё эффективнее)

4) begin и end не сравниваются из-за тог, что тогда такое условие не выполнится:
Код
C++ (Qt)
   tex_string_iterator<char> iter(buffer.begin(), buffer.end(), expr);
   tex_string_iterator<char> end(buffer.end(), buffer.end(), expr);
 
   for (; iter != end; ++iter) { // У iter и у end не совпадают диапазоны
       std::cout << *iter;
   }
 
 
Это можно решить, например, если передавать в конструктор три итератора: начало и конец последовательности и + ещё текущий итератор..
или ссылку на строку + итератор..   
 
Записан

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

Arch Linux Plasma 5
OKTA
Гость
« Ответ #8 : Апрель 22, 2014, 08:26 »

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

Я еще далеко не профессионал, но знаю, что профессиональный код пишется "для дебилов". Не раз заглядывал в код, который пишется для архи-сложных систем и там все просто, как два байта переслать  Смеющийся А тут застрелиться желание возникает, нежели разобраться, как и что работает)))))

Хотите способ, как лишить девственности Ваши наивные представления о профессиональном коде и решениях?   
Полистайте перед сном  исходники boost'а, особенно boost::spirit
Возможно, после этого ваше мнение измениться..  Улыбающийся

А вообще, дело даже не в конкретной реализации.. Вам не нужно знать что скрыто под капотом.. Важно архитектурные решения, сами подходы к решению проблем.. Гибкость и расширяемость.
Вот igors не разобравшись с проблемой, полез в копания каких то не существенных деталей.. частностей..  А Вы ведётесь на это(   

Хорошо, почитаю  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Апрель 22, 2014, 13:00 »

Хотите способ, как лишить девственности Ваши наивные представления о профессиональном коде и решениях?   
Полистайте перед сном  исходники boost'а, особенно boost::spirit
Возможно, после этого ваше мнение измениться..  Улыбающийся
Заметьте как резко возросла Ваша самооценка Улыбающийся Вы уже знаете как пишут профессиональный код, смело считаете представления других наивными и.т.п.

А ведь это всего лишь один из возможных подходов. Полистайте напр исходники Bullet, а можно и просто Qt, и... о боже - никакого буста нет! Да и std если и найдется, то жалкие крохи. Как и во многих др уважаемых мною исходниках - и это не мешает им иметь большой успех.

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

Обычным оправданием приводится "общность", т.е. это работает и для std::string и для QString и еще для бог весть чего. Но тогда чего у Вас юзается char (ведь уникод гораздо больше в масть). И не слишком ли высока цена пресловутой "общности"? Чем не устраивал QString? Наверное хотелось "профессионально" - так профессионал ценит время свое и других.

По поводу "красивых концепций" - они не всегда совпадают с результатом. Если boost::spirit безумно крут, то чего Вам приходится прилагать заметные усилия для относительно несложной (и вполне типовой) задачи пропустить комменты?

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

Сообщений: 4349



Просмотр профиля
« Ответ #10 : Апрель 22, 2014, 13:29 »

Эээээ. Так m_ax не использует, надеюсь пока, spirit. Улыбающийся
Здесь только токинайзер и регулярка.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #11 : Апрель 22, 2014, 15:03 »

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

А ведь это всего лишь один из возможных подходов. Полистайте напр исходники Bullet, а можно и просто Qt, и... о боже - никакого буста нет! Да и std если и найдется, то жалкие крохи. Как и во многих др уважаемых мною исходниках - и это не мешает им иметь большой успех.
Так я и говорю, что наивно пологать, что проффесиональный код - это код написанный "для дебилов". boost тому доказательство. Я ни чего не имею против Qt или Bullet )

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

Обычным оправданием приводится "общность", т.е. это работает и для std::string и для QString и еще для бог весть чего. Но тогда чего у Вас юзается char (ведь уникод гораздо больше в масть). И не слишком ли высока цена пресловутой "общности"? Чем не устраивал QString? Наверное хотелось "профессионально" - так профессионал ценит время свое и других.

Это всего лишь черновой вариант (первое приближение) где более важен сам подход. С общьностью проблем сейчас никаких нет. Немного причесал код.. теперь можете использовать и QString и std::string или что то своё..
Код
C++ (Qt)
#include <list>
#include <iterator>
#include <boost/regex.hpp>
#include <boost/range/istream_range.hpp>
#include <algorithm>
 
template <class BidirectIter, class Traits = std::iterator_traits<BidirectIter>>
class tex_iterator
{
public:
   typedef BidirectIter iterator;
   typedef typename Traits::value_type value_type;
   typedef typename Traits::pointer pointer;
   typedef typename Traits::reference reference;
   typedef typename Traits::difference_type difference_type;
   typedef typename std::bidirectional_iterator_tag iterator_category;
 
 
   typedef boost::basic_regex<value_type> regex_type;
 
   tex_iterator(iterator begin, iterator end, const regex_type & comment)
       : _begin(begin), _end(end), _it(begin), _comment(comment)
   {
       make_comments_list();
       if (_comments_list.begin()->begin() == _begin)
           ++*this;
   }
 
   tex_iterator() {}
 
   reference operator*() const { return *_it; }
 
   pointer operator->() const { return _it; }
 
   tex_iterator<BidirectIter, Traits>& operator++() {
       auto cur = _it;
       ++_it;
       for (const auto & comment : _comments_list) {
           if ((comment.begin() == _it) || (comment.begin() == cur)) {
               _it = comment.end();
               if (_it == _end)
                   break;
               ++_it;
           }
       }
 
       return *this;
   }
 
   tex_iterator<BidirectIter, Traits> operator++(int) {
       tex_iterator<BidirectIter, Traits> tmp = *this;
       ++*this;
       return tmp;
   }
 
   tex_iterator<BidirectIter, Traits>& operator--() {
       auto cur = _it;
       --_it;
       for (const auto & comment : _comments_list) {
           if ((comment.end() == _it) || (comment.end() == cur)) {
               _it = comment.begin();
               if (_it == _begin)
                   break;
               --_it;
           }
       }
 
       return *this;
   }
 
   tex_iterator<BidirectIter, Traits> operator--(int) {
       tex_iterator<BidirectIter, Traits> tmp = *this;
       --*this;
       return tmp;
   }
 
   template <class It, class T>
   friend bool operator==(const tex_iterator<It, T> &, const tex_iterator<It, T> &);
 
   template <class It, class T>
   friend bool operator!=(const tex_iterator<It, T> &, const tex_iterator<It, T> &);
 
private:
   iterator _begin;
   iterator _end;
   iterator _it;    //current iterator
   regex_type _comment;
   std::list<boost::iterator_range<iterator>> _comments_list;
 
   void make_comments_list() {
       if (_begin == _end)
           return;
 
       auto first = _begin;
       boost::match_results<iterator> what;
       while (boost::regex_search(first, _end, what, _comment)) {
           _comments_list.push_back(boost::iterator_range<iterator>(what[1].first, what[1].second));
           first = what[1].second;
       }
   }
};
 
template<class It, class T>
inline bool operator==(const tex_iterator<It, T> & x, const tex_iterator<It, T> & y) {
   return (x._it == y._it);
}
 
template<class It, class T>
inline bool operator!=(const tex_iterator<It, T> & x, const tex_iterator<It, T> & y) {
   return !(x == y);
}
 

Используется так:
Код
C++ (Qt)
   std::string str = "text1, #commented text\n text3,";
 
   tex_iterator<std::string::const_iterator> it(str.begin(), str.end(), boost::regex("(#[^\n]*)"));
   tex_iterator<std::string::const_iterator> end(str.end(), str.end(), boost::regex("(#[^\n]*)"));
 
   for (; it != end; ++it)
       std::cout << *it;
 

Почему не хочу QString:
во-первых не зочу тащить зависимости от Qt,
во-вторых, boost предоставляет более гибкие решения по разбору текста, чем Qt.
  
  
« Последнее редактирование: Апрель 22, 2014, 16:03 от m_ax » Записан

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

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

Сообщений: 2094



Просмотр профиля
« Ответ #12 : Апрель 22, 2014, 15:05 »

Эээээ. Так m_ax не использует, надеюсь пока, spirit. Улыбающийся
Здесь только токинайзер и регулярка.

Пока только изучаю)
Записан

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

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #13 : Апрель 22, 2014, 15:54 »

Нет содержательных имен методов/вызовов за которые хотелось бы зацепиться, все свалено в операторы/итераторы.
Это вообще один итератор. Какие имена методов вы хотите видеть у итератора, когда у него есть только две поддерживаемые им операции: вперед и назад? ++/-- для вас малоинформативны?

Как использовать этот код повторно? По-моему никак, он заточен на одну конкретную задачу.
Его можно использовать везде, где может понадобиться пропускать области данных с заданными маркерами начала и конца.
Что еще можно требовать от маленького итератора? Улыбающийся
Записан
Bepec
Гость
« Ответ #14 : Апрель 22, 2014, 16:10 »

Old - как человек слабо осведомлённый о бусте я вам гарантирую - что нихрена непонятно Веселый И чтобы его преобразовать для моего "гипотетического" проекта мне нужно много времени. Улыбающийся
Методов нет, всё упирается в буст и его знание Улыбающийся

PS тот, кто уже изучил это - может поправить под свой проект. Кто не изучал - тому просто невыгодно суваться Улыбающийся
Записан
Страниц: [1] 2 3 ... 8   Вверх
  Печать  
 
Перейти в:  


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