I have multiple floating point numbers lines, numbers in a line are space separated e.g.
1.2 2.2 3.2
1.1 2.1 3.1
I want to extract the above numbers as strings and parse to a 2D vector as;
std::vector< std::vector< std::string > > { {"1.2", "2.2", "3.2"},{"1.1", "2.1", "3.1} }
My code is like below.
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <string>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using VecType = std::vector< std::vector< std::string >>;
struct employee
{
VecType name;
};
}
BOOST_FUSION_ADAPT_STRUCT(
client::employee,
(client::VecType, name)
)
//]
namespace client
{
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, VecType(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::lexeme;
using ascii::char_;
number %= lexeme[+char_( "0-9." ) >> qi::space ];
start %= +number;
}
qi::rule<Iterator, std::string(), ascii::space_type> number;
qi::rule<Iterator, VecType(), ascii::space_type> start;
};
}
But this produces 2D vector which the outer vec size is 6 and each inner vector size is 1.
I don't understand how to split the string from the new line only to make only 2 inner vectors.
You have to split up the rules. Let's start with the types:
Now, let's make a rule to parse a number, a row of numbers and multiple rows:
Implementing them (note that I moved the skipper into the grammar because it's not a good idea to leak that into the interface):
Note: I used
blank
instead ofspace
because we do NOT want to skip theeol
which is significant for the grammar.DEMO
Live On Coliru
Prints
BONUS
Strong typing makes everything more fun: why parse into strings if you can parse into doubles?
Also showing how to enable rule debugging:
Live On Coliru
Prints