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

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

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

Сообщений: 2095



Просмотр профиля
« Ответ #15 : Март 10, 2016, 12:28 »

Как по мне, так лучше потратить пару дней на изучение boost::xpressive http://www.boost.org/doc/libs/1_60_0/doc/html/xpressive.html или spirit, чем каждый раз лепить такое..
Записан

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

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

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Март 10, 2016, 12:59 »

Как по мне, так лучше потратить пару дней на изучение boost::xpressive http://www.boost.org/doc/libs/1_60_0/doc/html/xpressive.html или spirit, чем каждый раз лепить такое..
В более общем случае - нужно что-то иметь, какие-то тулзы, чтобы не решать такие задачки всякий раз с нуля. Ну к этому пониманию надо еще прийти...
Записан
Bepec
Гость
« Ответ #17 : Март 10, 2016, 13:38 »

После знакомства с одной прожкой в 2000 строк, которая требовала буст, питон, луа и ещё около пяти дополнительных библиотек, я стараюсь пользоваться стандартными средствами.

Конечно если их нехватает или они не дают нужный функционал, беру библиотеки, но... осторожненько.

PS мучался я с той прожкой около 2 дней. Сотни пересборок библиотек, поиск нужных их версий, раскапывание архивов в поисках уже не существующих сайтов...
Записан
Vamireh
Гость
« Ответ #18 : Март 12, 2016, 17:49 »

Туда же. Где-то читал идею, что не надо бояться использовать велосипеды и дублирование кода (вот только не надо впадать в крайности). Типа вынесение любой повторяющейся последовательности в отдельную функцию усложняет зависимости в коде, а бездумное использование сторонних средств ведет к тому, что описал выше Верес.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #19 : Март 14, 2016, 15:30 »

Взгляд пал на спирит.
За основу взял пример с парсингом комплексных чисел и переделал на свой лад. Прошу помочь улучшить код. Интересует прямое использование QString (как??)
Код
C++ (Qt)
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <QString>
 
#include <iostream>
#include <string>
 
constexpr int nodeDimension = 3;
struct ParsedNode{
   uint number = -1;
   std::array<float, nodeDimension> coordinates = {{-1, -1, -1}};
};
 
template <typename Iterator>
bool parse_hypermesh(Iterator first, Iterator last, ParsedNode& node)
{
   using boost::spirit::qi::uint_;
   using boost::spirit::qi::float_;
   using boost::spirit::qi::_1;
   using boost::spirit::qi::phrase_parse;
   using boost::spirit::ascii::space;
   using boost::phoenix::ref;
 
   uint nodeNumber;
   float x;
   float y;
   float z;
 
   bool result = phrase_parse(first, last,
       (
           "*node(" >> uint_[ref(nodeNumber) = _1] >> ','
           >> float_[ref(x) = _1] >> ','
           >> float_[ref(y) = _1] >> ','
           >> float_[ref(z) = _1] >> ','
           >> *(uint_ >> ',')
           >> uint_ >> ')'
       ),
       space);
 
   if (!result || first != last){
       return false;
   }
 
   node.number = nodeNumber;
   node.coordinates = {x, y, z};
   return result;
}
 
int main()
{
   const QString testString("*node( 363484 , 232.7625 , -113.996 , 40.69956 , 0 , 0 , 0 , 0 , 0 )");
 
   const std::wstring& convertedTestString = testString.toStdWString();
   ParsedNode node;
 
   if (parse_hypermesh(convertedTestString.begin(), convertedTestString.end(), node))
   {
       std::cout << "Parsing succeeded\n";
   }
   else
   {
       std::cout << "Parsing failed\n";
   }
 
   return 0;
}
 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #20 : Март 14, 2016, 16:25 »

А зачем создавать в parse_hypermesh временные переменные?
Код
C++ (Qt)
uint nodeNumber;
   float x;
   float y;
   float z;
 

Можно же сразу в Node писать..

Код
C++ (Qt)
using namespace boost::spirit;
namespace phx = boost::phoenix;
namespace sw = boost::spirit::standard_wide;
 
struct Node
{
   static constexpr uint nodeDimension = 3;
   uint number = -1;
   std::array<float, nodeDimension> coordinates = {{-1, -1, -1}};
};
 
template <typename Iterator>
bool parse_hypermesh(Iterator first, Iterator last, Node& node)
{
   return qi::phrase_parse(first, last,
       (
           qi::lit("*node(") >> qi::uint_[phx::ref(node.number) = _1] >> ','
           >> qi::float_[phx::ref(node.coordinates[0]) = _1] >> ','
           >> qi::float_[phx::ref(node.coordinates[1]) = _1] >> ','
           >> qi::float_[phx::ref(node.coordinates[2]) = _1] >> ','
           >> *(qi::uint_ >> ',')
           >> qi::uint_ >> ')'
       ),
       sw::space) && first == last;
}
 
int main()
{
       std::string str = "*node( 363484 , 232.7625 , -113.996 , 40.69956 , 0 , 0 , 0 , 0 , 0 )";
 
       Node node;
 
       if (parse_hypermesh(str.begin(), str.end(), node))
       {
           std::cout << "Parsing succeeded\n";
           std::cout << node.number << std::endl;
           for (auto x : node.coordinates)
               std::cout << x << std::endl;
       }
       else
       {
           std::cout << "Parsing failed\n";
       }
   return 0;
}
 

Напрямую QString использовать  не получится.. Здесь надо писать специализацию std::char_traits для QChar.. 
Записан

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

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

Сообщений: 2130



Просмотр профиля
« Ответ #21 : Март 14, 2016, 16:29 »

Да, я и буду писать сразу в node. Просто уподобился тому, что было в примере. Так понимаю, что временные переменные для того, чтобы не испортить исходные данные.

Здесь надо писать специализацию std::char_traits для QChar.. 
Как? Это возможно сделать вне библиотеки?

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

Сообщений: 2095



Просмотр профиля
« Ответ #22 : Март 14, 2016, 16:57 »

Цитировать
Да, я и буду писать сразу в node. Просто уподобился тому, что было в примере.
Вообще если предполагается парсить сразу список нодов, то лучше написать отдельно свою грамматику (отнаследоваться от qi::grammar). Я бы так сделал..
Тогда на выходе будет контейнер с нодами (как то так):
Код
C++ (Qt)
template <class ForwardIterator, class Skipper>
class NodeParser : public qi::grammar<ForwardIterator, Node(), Skipper>
{
...
};
 
template <class ForwardIterator, class Container>
bool node_parse(ForwardIterator begin,
                 ForwardIterator end,
                 Container & container)
{
   return qi::phrase_parse(begin, end, *NodeParser<ForwardIterator, sw::space_type>(), sw::space, container);
}
 

Цитировать
Как? Это возможно сделать вне библиотеки?
Возможно.. http://en.cppreference.com/w/cpp/string/char_traits
Я сам этим не страдал, но теоретически прикрутить QString возможность есть..
Записан

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

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

Сообщений: 2130



Просмотр профиля
« Ответ #23 : Март 14, 2016, 17:01 »

Про grammar пока не читал. Спасибо за пищу.
А есть ли смысл прикручивать QString? Дело в том, что я читаю сейчас из файла с помощью QFile и QTextStream. Быть может имеет смысл перейти на классы стандартной библиотеки в данном случае?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #24 : Март 14, 2016, 17:19 »

Цитировать
А есть ли смысл прикручивать QString?
Я лично пока не вижу)

Цитировать
Дело в том, что я читаю сейчас из файла с помощью QFile и QTextStream. Быть может имеет смысл перейти на классы стандартной библиотеки в данном случае?
Да, можно:
Код
C++ (Qt)
typedef boost::spirit::istream_iterator istream_iterator_type;
       std::ifstream in(filename);
       in.unsetf( std::ios_base::skipws );
 
       istream_iterator_type beg( in );
       istream_iterator_type end;
       std::vector<node> container;
       node_parse(beg, end, container);
 
« Последнее редактирование: Март 14, 2016, 17:20 от m_ax » Записан

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

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

Сообщений: 2130



Просмотр профиля
« Ответ #25 : Март 14, 2016, 17:21 »

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

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Март 14, 2016, 17:34 »

Кстати, если уж нужна тупо "форматка", то почему не так?
Код
C++ (Qt)
#include <stdio.h>
 
int main( void )
{
 int num, last = 0;
 float val[3] = { 1, 2, 3 };
 
 const char * fmt = "node ( %d , %f, %f, %f ) %d";
 const char * test = "node ( 363484   ,232.7625,    -113.996, 40.69956)777";
//  const char * test = "node(363484,232.7625,-113.996,40.69956)777";
 
 int count = sscanf(test, fmt, &num, val, val + 1, val + 2, &last);
 printf("Ok = %d\n", int(last == 777));
 printf("%d (%f, %f, %f)\n", num, val[0], val[1], val[2]);
 
 return 0;
}
Что здесь плохо и при каких данных заклинит?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #27 : Март 14, 2016, 17:37 »

sscanf плохо. и printf плохо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Март 14, 2016, 17:54 »

sscanf плохо. и printf плохо.
А чем конкретно? Или только тем что "не модно"?  Улыбающийся
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #29 : Март 14, 2016, 17:55 »

Саттер так сказал, а я ему верю. Давайте не будем начинать холивара.
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


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