2015-04-24 3 views
5

Мое намерение состоит в том, чтобы разделить список значений, разделенных запятыми, на вложенный вектор. Этот список является двумерным. Основной вопрос:Проанализируйте вектор <vector <double>> с boost :: spirit

Можно ли проанализировать вектор вектора с boost :: spirit?

Что-то вроде таблицы под «трэкшн»:

' 
' RPM 
0,5000,10000,15000,20000,25000 
' 
' Temp 
' 
-40.,0.,20.,40. 
' 
' Traction 
200.,175.,170.,165.,160.,150. 
200.,175.,170.,165.,160.,150. 
165.,165.,160.,155.,145.,145. 
160.,155.,150.,145.,145.,140. 
' 

На следующем этапе, я хотел бы читать в 4-мерных данных, но сейчас я борюсь со вторым измерением. Структура данных, как это:

struct table { 
    std::vector<double> index; 
    std::vector<double> index2; 
    std::vector<std::vector<double> > base; 
}; 

грамматика ИМХО довольно просто следующим образом:

comment %= qi::lexeme[ '\'' >> *(qi::standard::char_ - qi::eol)] >> qi::eol; 
commentblock = comment >> *(comment); 
doublevector = qi::double_ % ',' >> qi::eol ; 
vectorblock = *doublevector; 
start = commentblock   >> 
     doublevector   >> 
     commentblock   >> 
     doublevector   >> 
     commentblock   >> 
     vectorblock    >> 
     commentblock   >> 
     qi::eoi 
     ; 

До сих пор, у меня нет никаких проблем при разборе два вектора index и index2. Но проблема начинается с base. Я считаю, что крайне важно раздел, где я определяю vectorblock:

vectorblock = *doublevector; 

Я попробовал несколько вариантов этого заявления. Также оператор %= от this вопрос ничего не менял. Хотя распространение атрибутов может быть правильным направлением.

Если я следовать примеру подталкивание документации "with style", результат точно такой же:

vectorblock = doublevector % qi::eps; 

Образцы Список Redux, которые используют push_back():

vectorblock = doublevector[phoenix::push_back(qi::_val, qi::_1)] % qi::eps; 

спровоцировать поток ошибок компиляции , начиная с:

ошибка C2039: 'push_back': не является членом 'буст :: дух :: unused_type'

Update: Проблема заключалась в объявлении vectorblock. Я забыл () после типа атрибута. Таким образом, определение должно выглядеть следующим образом:

qi::rule<Iterator, std::vector<std::vector<double> >(), Skipper> vectorblock; 

The (обновлена) рабочий пример здесь:

#include <iostream> 
#include <string> 
#include <vector> 

#define BOOST_SPIRIT_DEBUG 

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/fusion/adapted.hpp> 

struct table { 
    std::vector<double> index; 
    std::vector<double> index2; 
    std::vector<std::vector<double> > base; 
}; 

BOOST_FUSION_ADAPT_STRUCT(
     table, 
     (std::vector<double> , index) 
     (std::vector<double> , index2) 
     (std::vector<std::vector<double> >, base) 
) 

const std::string contents = 
     "'\n" 
     "' RPM\n" 
     "'\n" 
     "0,5010,10000,15000,20000,25000\n" 
     "'\n" 
     "' Temp\n" 
     "'\n" 
     "-40.,0.,20.,40.\n" 
     "'\n" 
     "' Traction\n" 
     "200.,175.,170.,165.,160.,150.\n" 
     "200.,175.,170.,165.,160.,150.\n" 
     "165.,165.,160.,155.,145.,145.\n" 
     "160.,155.,150.,145.,145.,140.\n" 
     "'\n" 
; 


int main() 
{ 
    namespace qi = boost::spirit::qi; 
    namespace phoenix = boost::phoenix; 

    typedef std::string::const_iterator Iterator; 
    typedef boost::spirit::ascii::blank_type Skipper; 

    qi::rule<Iterator, std::string(), Skipper> comment; 
    qi::rule<Iterator, Skipper> commentblock; 
    qi::rule<Iterator, std::vector<double>(), Skipper> doublevector; 
    qi::rule<Iterator, std::vector<std::vector<double> >, Skipper> vectorblock; 
    qi::rule<Iterator, table(), Skipper> start; 

    comment %= qi::lexeme[ '\'' >> *(qi::standard::char_ - qi::eol)] >> qi::eol; 
    commentblock = comment >> *(comment); 

    doublevector = qi::double_ % ',' >> qi::eol ; 
    vectorblock = *doublevector; 

    start = commentblock   >> 
      doublevector   >> 
      commentblock   >> 
      doublevector   >> 
      commentblock   >> 
      vectorblock    >> 
      commentblock   >> 
      qi::eoi 
      ; 

    BOOST_SPIRIT_DEBUG_NODES((start)(doublevector)(vectorblock)); 

    table tref; 

    bool rv = qi::phrase_parse(
        std::begin(contents), std::end(contents), 
        start, 
        boost::spirit::ascii::blank, 
        tref 
       ); 

    std::cout << "parse " << ((char *)rv?"success":"failure") << ".\n"; 

    for (auto i : tref.index) 
     std::cout << i << ", "; 
    std::cout << "\n"; 
    for (auto i : tref.index2) 
     std::cout << i << ", "; 
    std::cout << "\nBase:\n"; 
    for (auto & i : tref.base) 
    { 
     for(auto & j : i) 
      std::cout << j << ", "; 
     std::cout << "\n"; 
    } 
    std::cout << std::endl; 

} 
+4

Вы забыли '()' в типе атрибута правила объявление для 'vectorblock'. После того, как я положил его, он работал для меня с '* doublevector'. – Wintermute

+0

Вы правы. дурак я! – user23573

ответ

3

Ответ да. На самом деле довольно тривиально разобрать на vector<vector<double> >

Для определения правила требуется тип функции, а не тип напрямую. Это просто объясняется here.Более подробное объяснение, вероятно, найти в документации boost::phoenix

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

parse success. 
0, 5011, 10000, 15000, 20000, 25000, 
-40, 0, 20, 40, 
Base: 
200, 175, 170, 165, 160, 150, 
200, 175, 170, 165, 160, 150, 
165, 165, 160, 155, 145, 145, 
160, 155, 150, 145, 145, 140, 
Смежные вопросы