I want to parse a lot of Lat/Long coordinates with the following format 1.123456W or 50.123456N, basically a double followed by a char ('N', 'S', 'W', 'E'). I just want to remove the character from the string, convert to double and change the sign if its W-est or S-outh. The following code works in three out of four cases:
This works for 1.123456W, or 50.123456N, or 9.123456S, but not for 7.123456E. I'm guessing the Qi parser expects an E at the input string to correlate with an exponent representation of a double and fails because its incomplete? But how do I tell Qi to skip the exponent if it fails an just decodes the string to the point of where the E resides?
double d;
char c;
auto const expr = boost::spirit::qi::double_ >> boost::spirit::qi::char_;
std::string tok = "7.123456E";
bool success = boost::spirit::qi::parse( tok.cbegin(), tok.cend(), expr, d, c ) ) {
if( success ) {
if( c == 'W' || c == 'w' || c == 'S' || c == 'S' ) {
d = -d;
}
/// ....
}
Thank you very much!
Here you go. The Coliru compiler didn't like your use of auto
, so I made a minimal change to fix it.
Have a look at the RealPolicies documentation I supplied above. You create a new policy class based on the ureal_policies
template, override the exponent-related methods and return false from them.
#include <iostream>
#include <boost/spirit/include/qi.hpp>
using namespace std;
//create a real number parser policy that doesn't handle exponent notation
template <typename T>
struct no_exp_policy : boost::spirit::qi::ureal_policies<T>
{
// No exponent
template <typename Iterator>
static bool
parse_exp(Iterator&, Iterator const&)
{
return false;
}
// No exponent
template <typename Iterator, typename Attribute>
static bool
parse_exp_n(Iterator&, Iterator const&, Attribute&)
{
return false;
}
};
int main(int argc, char **argv) {
double d;
char c;
// no_exp is a real number parser that ignores exponents and has a double attribute
boost::spirit::qi::real_parser<double, no_exp_policy<double> > no_exp;
std::string tok = "7.123456E";
bool success = boost::spirit::qi::parse( tok.cbegin(), tok.cend(),
no_exp >> boost::spirit::qi::char_("NESWnesw"),
d, c );
if( success ) {
if( c == 'W' || c == 'w' || c == 'S' || c == 's' ) {
d = -d;
}
cout << d << " " << c << endl;
}
else
cout << "failed" << endl;
return 0;
}
Output:
7.12346 E
Hope this helps, though I agree it's a bit long-winded. I'm still not 100% sure it's not a spirit error that 7.12346E is handled by the default real parser as a real number, as IMHO you need to have an exponent value after the E to make it valid.