我有一个需要解析双数字的库,它总是使用一个点'。'作为小数分隔符。不幸的是,对于这种情况,strtod()尊重可能使用不同分隔符的语言环境,因此解析可能会失败。我不能setlocale() - 它不是线程安全的。所以我现在正在寻找一个干净的与语言环境无关的strtod实现。到目前为止,我已经找到了多个实现,但是所有这些实现看起来都很糟糕,或者就像坏代码一样。 有人可以为我推荐经过充分测试,工作,干净(ANSI)C的实现吗?
答案 0 :(得分:3)
获取一些已知的实现(不依赖于atof
),例如与ruby一起分发的实现:
ruby_1_8/missing/strtod.c
答案 1 :(得分:3)
警告:来自ruby的建议实现包含错误。 我不介意gavin指出的小差异,但如果你试图解析像“0.000000000000000000000000000000000000783475”这样的东西,你将得到0.0而不是7.834750e-37(就像股票strtod()返回。)
其他解决方案:
#include <sstream>
#include "strtod_locale_independent.h"
extern "C" double strtod_locale_independent(const char* s)
{
std::istringstream text( s );
text.imbue(std::locale::classic());
double result;
text >> result;
return result;
}
我不知道这有多快。
答案 2 :(得分:2)
根据上面的答案,我尝试在ruby_1_8/missing/strtod.c使用Ruby实现。但是,对于某些输入,这给出了gcc内置解析器的不同答案,以及来自stdlib.h的strtod,无论是在Mac上还是在Linux平台上:
char * endptr ;
double value1 = 1.15507e-173 ;
double value2 = strtod( "1.15507e-173", &endptr ) ;
double value3 = test_strtod( "1.15507e-173", &endptr ) ;
assert( sizeof( double ) == sizeof( unsigned long ) ) ;
printf( "value1 = %lg, 0x%lx.\n", value1, *(unsigned long*)( &value1 ) ) ;
printf( "value2 = %lg, 0x%lx.\n", value2, *(unsigned long*)( &value2 ) ) ;
printf( "value3 = %lg, 0x%lx.\n", value2, *(unsigned long*)( &value3 ) ) ;
assert( value1 == value2 ) ;
assert( value1 == value3 ) ;
打印
value1 = 1.15507e-173, 0x1c06dace8bda0ee0.
value2 = 1.15507e-173, 0x1c06dace8bda0ee0.
value3 = 1.15507e-173, 0x1c06dace8bda0edf.
Assertion failed: (value1 == value3), function main, file main.c, line 16.
所以我的建议是在使用前测试所选的实现。
答案 3 :(得分:0)
netlib上还提供了gdtoa,BSD风格的许可证:http://www.netlib.org/fp/gdtoa.tgz