我正在为编程语言编写一个解释器,我用C ++语言编写,坦白说,我很坦率。
我想要完成的是在std::string
转换特定的浮动格式
到一个双(或其他)。我希望它完全独立于语言环境,并尽可能强大。
我有两个案例:
.4
或4.
),但不能同时我希望它能成为“C ++方式”。是否有一个函数可用于指定自定义数字格式(类似于PHP中的date
)。
我将非常感谢所提供的任何指针或代码片段。谢谢!
答案 0 :(得分:2)
我不知道iostream支持严格的输入格式化。
但是,你可以使用Boost Spirit:
请参阅http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html
这将允许您明确定义为指数,符号和任何(数千)分隔符接受的格式。这也是一种非常复杂的方法,但它非常快速且非常灵活(适用于非标准数字类型,IIRC)。
您可以使用Spirit Qi规则指定确切的格式,只有符合您的要求时才将raw[]
输入序列传递给标准数字解析器。
更多参与,但也更优化的方式,是使用精神词汇表来标记输入 - 有效地做同样但更有效。
这里的中间地点是使用普通的(Posix | Perl | C ++ 11 | Boost)正则表达式来验证输入格式并将其传递给任何合适的转换(如Boost Lexical cast,或者只是std :: stringstream>> double等。)
示例在解析浮点数 的数字格式时显示Spirit Qi和正则表达式预匹配(语言 c ++ 0x 1 ) 子>:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/regex.hpp>
namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;
bool is_ok(const std::vector<char>& raw)
{
static const boost::regex rx(R"(-?(\d*\.\d+|\d+\.\d*))");
return boost::regex_match(raw.begin(), raw.end(), rx);
}
template <typename Input>
void test(const Input& input)
{
auto f(std::begin(input)), l(std::end(input));
double parsed = 0;
bool ok = qi::phrase_parse(f, l,
// this is the parser expression
&(+qi::char_)[ qi::_pass = phx::bind(is_ok, qi::_1) ]
>> qi::double_,
// end parser expression
qi::space, parsed);
std::cout << "DEBUG: '" << input << "'\t" << std::boolalpha << ok << "\t" << parsed << std::endl;
}
int main()
{
const std::string good[] = { ".300", "300.", "-.4", "-4." };
const std::string wrong[] = { "", ".", "1", "-1", "-1111", "3..", "+1", "+.1", "+1.", "+1.0", "+-2.", "-+2." };
for (auto& input : good)
test(input);
for (auto& input : wrong)
test(input);
}
<子> 1 使用c ++ 11 featurs:
答案 1 :(得分:0)
假设你的意思是字符串属于C
语言环境:
template<class T>
std::string tostring(const T& input)
{
stringstream ss;
if (!(ss << input))
throw std::runtime_error("cannot convert!");
return ss.str();
}
template<class T>
void fromstring(const std::string& input, T& output)
{
stringstream ss(input);
if (!(ss >> output) || ss)
throw std::runtime_error("cannot convert!");
}
//Passes output as parameter, in case it's not copiable.
int main() {
float pi = 3.14159f; //pi to string and back
std::string strpi = tostring(pi);
fromstring(strpi, pi);
std::ifstream in("in.txt"); //copies a file through a string
std::string file = tostring(in);
std::ofstream out("out.txt");
fromstring(file, out);
return 0;
}
答案 2 :(得分:0)
整数:它们应该是0-9的连续数字,带或不带前导减号(不允许加号,允许前导零)
浮点数:[整个部分]。[小数部分]有或没有前导减号且没有任何千位分隔符。可以省略整个部分或小数部分(例如.4或4.),但不能同时使用
这些几乎不是“自定义格式”;它们可以通过stringstream
完美地解析(或者,如果您使用BOOST,则lexical_cast
)。
#include <iostream>
#include <string>
#include <sstream>
int main( ... ) {
std::string s = "-1.0";
float f = 0;
if( std::stringstream(s) >> f ) {
std::cout << f;
}
else {
std::cout << "No good!";
}
return 0;
}