将 u16string 转换为 float
Convert u16string to float
我有一个utf16编码的字符串,我想把它转换成浮点数
例如
如果有一个像 u"1342.223"
这样的 utf16 字符串,它应该 return 1342.223
浮点数,如果它是 utf8 我曾经使用 stod
函数转换它,但是如何在utf16 编码字符串 std::u16string
没有这方面的标准功能。如果您可以在恰好使用 16bit
宽字符的系统上使用 std::wstring
,则可以使用:
double d;
std::wistringstream(L"1342.223") >> d;
否则,您可以利用数字从 UTF-16
到 ASCII/UTF-8
的简单转换来编写快速转换函数。它并不理想,但应该相当有效:
double u16stod(std::u16string const& u16s)
{
char buf[std::numeric_limits<double>::max_digits10 + 1];
std::transform(std::begin(u16s), std::end(u16s), buf,
[](char16_t c){ return char(c); });
buf[u16s.size()] = '[=11=]'; // terminator
// some error checking here?
return std::strtod(buf, NULL);
}
如果您确实知道您的字符串是 nicely-formatted(例如没有空格),并且 当且仅当性能至关重要时(即如果您解析数百万或数十亿个数字),不要排除自己解码的可能性,循环遍历字符串。查找标准库源代码(也许比较 libc++ 和 libstdc++)以查看它们的作用,并对其进行调整。当然,在这些情况下,您还应该注意并行化您的工作,尝试利用 SIMD 等。
首先,将 utf16 numeric 字符串转换为窄字符串是微不足道的。即使您不能确定窄字符集是否为 7 位字符的 ASCII,C 也保证代码“0”到“9”应该是连续的,对于 Unicode(0x30 到 0x39)也是如此。所以代码可以很简单(仅取决于 <string>
包含:
double u16strtod(const std::u16string& u16) {
char *beg = new char[u16.size() + 1];
char *str = beg;
for (char16_t uc: u16) {
if (uc == u' ') *str++ = ' '; // special processing for possible . and space
else if (uc == u'.') *str++ = '.';
else if ((uc < u'0') || (uc > u'9')) break; // could use better error processing
else {
*str++ = '0' + (uc - u'0');
}
}
*str++ = '[=10=]';
char *end;
double d = strtod(beg, &end); // could use better error processing
delete[] beg;
return d;
}
如果narrow charset是ASCII就更简单了:
double u16strtod(const std::u16string& u16) {
char *beg = new char[u16.size() + 1];
char *str = beg;
for (char16_t uc: u16) {
if ((uc <= 0) || (uc >= 127)) break; // can only contain ASCII characters
else {
*str++ = uc; // and the unicode code IS the ASCII code
}
}
*str++ = '[=11=]';
char *end;
double d = strtod(beg, &end);
delete[] beg;
return d;
}
我有一个utf16编码的字符串,我想把它转换成浮点数
例如
如果有一个像 u"1342.223"
这样的 utf16 字符串,它应该 return 1342.223
浮点数,如果它是 utf8 我曾经使用 stod
函数转换它,但是如何在utf16 编码字符串 std::u16string
没有这方面的标准功能。如果您可以在恰好使用 16bit
宽字符的系统上使用 std::wstring
,则可以使用:
double d;
std::wistringstream(L"1342.223") >> d;
否则,您可以利用数字从 UTF-16
到 ASCII/UTF-8
的简单转换来编写快速转换函数。它并不理想,但应该相当有效:
double u16stod(std::u16string const& u16s)
{
char buf[std::numeric_limits<double>::max_digits10 + 1];
std::transform(std::begin(u16s), std::end(u16s), buf,
[](char16_t c){ return char(c); });
buf[u16s.size()] = '[=11=]'; // terminator
// some error checking here?
return std::strtod(buf, NULL);
}
如果您确实知道您的字符串是 nicely-formatted(例如没有空格),并且 当且仅当性能至关重要时(即如果您解析数百万或数十亿个数字),不要排除自己解码的可能性,循环遍历字符串。查找标准库源代码(也许比较 libc++ 和 libstdc++)以查看它们的作用,并对其进行调整。当然,在这些情况下,您还应该注意并行化您的工作,尝试利用 SIMD 等。
首先,将 utf16 numeric 字符串转换为窄字符串是微不足道的。即使您不能确定窄字符集是否为 7 位字符的 ASCII,C 也保证代码“0”到“9”应该是连续的,对于 Unicode(0x30 到 0x39)也是如此。所以代码可以很简单(仅取决于 <string>
包含:
double u16strtod(const std::u16string& u16) {
char *beg = new char[u16.size() + 1];
char *str = beg;
for (char16_t uc: u16) {
if (uc == u' ') *str++ = ' '; // special processing for possible . and space
else if (uc == u'.') *str++ = '.';
else if ((uc < u'0') || (uc > u'9')) break; // could use better error processing
else {
*str++ = '0' + (uc - u'0');
}
}
*str++ = '[=10=]';
char *end;
double d = strtod(beg, &end); // could use better error processing
delete[] beg;
return d;
}
如果narrow charset是ASCII就更简单了:
double u16strtod(const std::u16string& u16) {
char *beg = new char[u16.size() + 1];
char *str = beg;
for (char16_t uc: u16) {
if ((uc <= 0) || (uc >= 127)) break; // can only contain ASCII characters
else {
*str++ = uc; // and the unicode code IS the ASCII code
}
}
*str++ = '[=11=]';
char *end;
double d = strtod(beg, &end);
delete[] beg;
return d;
}