2016-04-14 4 views
1

konvertiert werden Ich versuche, einen Parser für die CSV-Datei mit der Bibliothek boost.spirit zu schreiben die folgenden Kompilierungsfehler: ich bin in Boost.Spirit, so könnte jemand die Gründe identifiziertboost.spirit Kompilierungsfehler: Argument 1 kann nicht von "const char *" in "std :: _ String_iterator <std :: _ String_val>

die Fehlermeldung lautet:.?

Fehler C2664: ‚Bool boost :: spirit :: Qi :: Regel :: parse (Iterator &, const Iterator &, Kontext &, const Skipper &, Attribut &) Nachteile t ': Konvertierung Argument 1 von 'const char *' auf 'std :: _ String_iterator >> &'

Und mein Code:

#pragma once 
#define BOOST_SPIRIT_USE_PHOENIX_V3 

#include<vector> 
#include<string> 
#include<memory> 
#include<boost/iostreams/device/mapped_file.hpp> // for mmap 
#include<boost/utility/string_ref.hpp> 
#include<boost/spirit/include/qi.hpp> 
#include<boost/spirit/include/qi_grammar.hpp> 
#include<boost/spirit/include/qi_real.hpp> 
#include<boost/spirit/include/phoenix.hpp> 
#include<boost/spirit/include/qi_symbols.hpp> 

typedef boost::string_ref CsvField; 
typedef std::vector<CsvField> CsvLine; 
typedef std::vector<CsvLine> CsvFile; 
namespace qi = boost::spirit::qi; 

template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> { 
    CsvParser() : CsvParser::base_type(lines) { 
     using namespace qi; 
     using boost::phoenix::construct; 
     using boost::phoenix::size; 
     using boost::phoenix::begin; 
     using boost::spirit::qi::float_; 

     field = raw[*~char_(",\r\n")][_val = construct<CsvField>(begin(qi::_1), size(qi::_1))]; // semantic action 
     //field = qi::float_; 
     line = field % ','; 
     lines = line % eol; 
    } 
    // declare: line, field, fields 
    qi::rule<T, CsvFile()> lines; 
    qi::rule<T, CsvLine()> line; 
    qi::rule<T, CsvField()> field; 
}; 

Der Code wirklich von Simplest way to read a CSV file mapped to memory? angenommen wird, so Ich habe keine Ahnung. Ich verwende Microsoft Visual Studio 2015 und boote 1.16.0.

Derselbe Fehler tritt auf, wenn ich typedef boost::string_ref CsvField durch typedef std::string ersetze, oder den Parser für Feld durch field = *(~char_(",\r\n")) ersetzen.

Auch die Datei, die ich analysiere, ist wirklich eine Standard-CSV-Datei, daher ist jeder Vorschlag von alternativen Analysemethoden willkommen. Der einzige Haken ist, dass die Datei Millionen von Zeilen enthält, so dass das standardmäßige zeilenweise Analysieren für mich nicht funktioniert.

Antwort

0

Sie zeigen den relevanten Code nicht an. Alles, was Sie haben, ist eine Template-Klasse, aber ob eine Instantiierung auch gut ausgebildet ist, hängt davon ab, wofür Sie sie instanziieren.

Momentan würde ich annehmen, dass Sie versuchen, mit std::string::const_iterator als der Iterator-Typ instanziieren - was ein bisschen lustig ist w.r.t. die Erwähnung von Memory Mapping und String_ref (was bedeuten würde, dass du alles Nullen machen willst).

Dennoch dann das Problem ist, dass raw[] eine iterator_range des Typs Quelle Iterator aussetzt, dh Sie std::string::const_iterator als erstes Argument des string_ref (alias CsvField) Konstruktor übergeben. Das wird nicht funktionieren.

In einer fix:

field = raw[*~char_(",\r\n")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action 

Um wirklich schön Sie std::addressof in einem Phoenix Schauspieler wickeln sollten und es statt operator& verwenden. Ich überlasse das als Übung für den Leser.

Live On Coliru

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include<boost/utility/string_ref.hpp> 
#include<boost/spirit/include/qi.hpp> 
#include<boost/spirit/include/phoenix.hpp> 

typedef boost::string_ref CsvField; 
typedef std::vector<CsvField> CsvLine; 
typedef std::vector<CsvLine> CsvFile; 

namespace qi = boost::spirit::qi; 

template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> { 
    CsvParser() : CsvParser::base_type(lines) { 
     using namespace qi; 
     using boost::phoenix::construct; 
     using boost::phoenix::size; 
     using boost::phoenix::begin; 
     using boost::spirit::qi::float_; 

     field = raw[*~char_(",\r\n")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action 
     //field = qi::float_; 
     line = field % ','; 
     lines = line % eol; 
    } 
    // declare: line, field, fields 
    qi::rule<T, CsvFile()> lines; 
    qi::rule<T, CsvLine()> line; 
    qi::rule<T, CsvField()> field; 
}; 

int main() 
{ 
    using It = std::string::const_iterator; 
    CsvParser<It> p; 

    std::string const input = R"([section1] 
key1=value1 
key2=value2 
[section2] 
key3=value3 
key4=value4 
)"; 

    CsvFile parsed; 
    auto f = input.begin(), l = input.end(); 
    bool ok = parse(f, l, p, parsed); 

    if (ok) { 
     std::cout << "Parsed: " << parsed.size() << " stuffs\n"; 
    } else { 
     std::cout << "Parse failed\n"; 
    } 

    if (f != l) 
     std::cout << "Remaining input: '" << std::string(f, l) << "'\n"; 
} 

Druck:

Parsed: 7 stuffs