2015-04-24 18 views
5

Meine Absicht ist es, eine kommagetrennte Liste von Werten in einen verschachtelten Vektor zu analysieren. Diese Liste ist zweidimensional. Die grundlegende Frage ist:In einen Vektor <Vektor <double>> mit boost :: spirit zerlegen

ist es möglich, in einen Vektor des Vektors mit boost :: spirit zu analysieren?

So etwas wie die Tabelle unter „Traction“:

' 
' 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. 
' 

In einem weiteren Schritt würde Ich mag in 4-dimensionalen Daten lesen, aber jetzt mit der zweiten Dimension Ich bin zu kämpfen. Die Datenstruktur ist wie folgt:

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

Die Grammatik ist IMHO ziemlich einfach wie folgt:

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 
     ; 

Bisher habe ich kein Problem Parsen der beiden Vektoren index und index2. Aber das Problem beginnt bei base. Ich denke, dass der entscheidende Abschnitt ist, wo ich die vectorblock definieren:

vectorblock = *doublevector; 

ich mehrere Varianten dieser Aussage versucht haben. Auch der %= Operator von this Frage hat nichts geändert. Obwohl die Attributausbreitung die richtige Richtung sein könnte.

Wenn ich die Boost-Dokumentation Beispiel "with style" folgen, ist das Ergebnis genau das gleiche:

vectorblock = doublevector % qi::eps; 

Die Liste Redux Proben, die push_back() verwenden:

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

provozieren eine Flut von Fehlern kompilieren , beginnend mit:

Fehler C2039: 'push_back': ist kein Mitglied von 'boost :: spirit :: unused_type'

Update: Das Problem bei der Erklärung der vectorblock war. Ich habe die () nach dem Attributtyp vergessen. So sollte die Definition wie folgt aussehen:

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

Die (aktualisiert) Arbeitsbeispiel ist hier:

#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

Sie haben vergessen, die '()' in dem Attributtyp der Regel Deklaration für "Vektorblock". Nachdem ich es dort hingelegt habe, hat es für mich mit '* doublevector' funktioniert. – Wintermute

+0

Sie sind richtig. wie dumm von mir! – user23573

Antwort

3

Die Antwort ist ja. Es ist eigentlich ziemlich trivial in vector<vector<double> >

zu analysieren Die Regeldefinition erfordert einen Funktionstyp, nicht den Typ direkt. Dies wird einfach erklärt here.schön die analysierten Werte Eine gründlichere Erklärung ist wahrscheinlich in der Dokumentation von boost::phoenix

Die Ausgabe des Programms gefunden oben zeigt nun:

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, 
Verwandte Themen