I am writing an interpreter for a programming language and I am doing it in a C++, a language, I am frankly quite new to.
What I am trying to accomplish is to convert a specific float format in std::string
to a double (or whatever). I want it to be completely independent of the locale and as robust as possible.
I have two cases:
- integers: they should be contiguous digits from 0-9 with or without a leading minus sign (no plus sign allowed, leading zeros allowed)
- floating-point numbers: [whole part].[decimal part] with or without a leading minus and without any thousands separators. Either whole part or decimal part can be ommitted (for example
.4or4.), but not both
I would like it to be the “C++ way” to do it. Is there a function I could use to specify custom number formats (kind of like date in PHP).
I will be very grateful for any pointer or code-snippet provided. Thank you!
I don’t know about iostreams support for strict input formatting.
However, you can use Boost Spirit:
standard real parsers with RealPolicy
See http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html
This will allow you to explicitely define the format(s) accepted for exponents, signs and any (thousands) separators. This is also a quite complex approach, but it is very fast and very flexible (works for non-standard numeric types too, IIRC).
Two phase parsing
You can use either Spirit Qi rules to specify the exact format, and pass the
raw[]input sequence of to the standard numeric parsers only if it matches your requirements.The more involved, but also more optimal way, would be to use a Spirit Lexer to tokenize the input – effectively doing the same but more efficiently.
The middle ground
The middle ground here would be to use a plain-old (Posix|Perl|C++11|Boost) regular expression to validate the input format and pass it off to any suitable conversion (like Boost Lexical cast, or just std::stringstream >> double etc.)
A sample showing both Spirit Qi and regex pre-matching at work while parsing the number format for floats (The language is c++0x1):
1 using c++11 featurs: