1

I've implemented simple ascii parser using boost::spirit. target ascii file looks like

n

0 23 45 10.0 0.5

.....

n-1 x y .....

but it returns in measure_list only 1 element

if I am trying to read ASCII as a simple vector<double> instead of structured for example - it works fine. Whats wrong?

struct measure
{
   int id;
   double x, y, size_, angle;
} 

BOOST_FUSION_ADAPT_STRUCT(measure, (int, id)(double, x)(double, y)(double, size_)(double, angel))

typedef std::vector<measure> data_t;

void RelativeMeasure(string filename)
        {
                clear();

                if(!filesystem::exists(filename)) return;

                file_name = filename;



                ifstream calibration_file(filename);

                if(calibration_file.is_open())
                {
                        int key_count;
                        calibration_file >> key_count;

                        istreambuf_iterator<char> eos;
                        istreambuf_iterator<char> it(calibration_file);

                        std::string strver(it, eos);

                        std::vector<measure> measure_list;
                        measure_list.reserve(100000);

                        qi::phrase_parse(strver.begin(), strver.end(), (qi::int_ > qi::double_ > qi::double_ > qi::double_ > qi::double_) % qi::eol, qi::blank, measure_list);

                        for each(auto measure in measure_list) key_list.push_back(KeyPoint(measure.x, measure.y, measure.size_, measure.angel));
}
Himanshu
  • 4,327
  • 16
  • 31
  • 39
Mike
  • 43
  • 1
  • 5
  • `(double, angel))` I think you mean to say `(double, angle))` – AndyG Apr 26 '15 at 20:54
  • Please construct an [MCVE](http://stackoverflow.com/help/mcve). It's very hard (if not impossible) to tell what could be broken in your real code from pseudocode that wouldn't compile even if it were complete. It could be anything from malformed input data (empty lines?) to undefined behavior in another part of the code that messes up the parser. – Wintermute Apr 26 '15 at 21:11

1 Answers1

0

The most likely culprit that I see is that you don't eat the newline after n. Perhaps also use +qi::eol as the delimiter.

But that doesn't explain that you'd read the first entry.

You could simplify things by using the streaming API (using boost::spirit::istream_iterator multi-pass adaptor under the hood):

Live On Coliru

void RelativeMeasure(std::string filename)
{
    std::ifstream calfile(filename, std::ios::binary);

    int key_count;
    std::vector<measure> measure_list;

    using namespace qi;
    if (
        calfile >> std::noskipws >> phrase_match(int_, blank, key_count)
        && calfile >> phrase_match(qi::repeat(key_count)[int_ > double_ > double_ > double_ > double_ > +eol], blank, measure_list)
    )
    {
        std::vector<KeyPoint> key_list;
        key_list.reserve(measure_list.size());
        // using a converting constructor (why not parse into this at once?)
        std::copy(measure_list.begin(), measure_list.end(), back_inserter(key_list));
    }
}
sehe
  • 374,641
  • 47
  • 450
  • 633