C++ 将u16string转换为float

C++ 将u16string转换为float,c++,unicode,utf-16,C++,Unicode,Utf 16,我有一个utf16编码的字符串,我想把它转换成float 例如 如果有一个utf16字符串,比如u“1342.223”,它应该以浮点形式返回1342.223,如果是utf8,我使用stod函数转换它,但是如何在utf16 enocoded字符串std::u16string上执行此操作没有标准函数。如果您可以在恰好使用16位宽字符的系统上使用std::wstring,则可以使用: double d; std::wistringstream(L"1342.223") >> d; 否则,

我有一个utf16编码的字符串,我想把它转换成float

例如

如果有一个utf16字符串,比如
u“1342.223”
,它应该以浮点形式返回
1342.223
,如果是utf8,我使用
stod
函数转换它,但是如何在utf16 enocoded字符串
std::u16string
上执行此操作没有标准函数。如果您可以在恰好使用
16位
宽字符的系统上使用
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()] = '\0'; // terminator

    // some error checking here?
    return std::strtod(buf, NULL);
}
双u16stod(std::u16string const&u16s) { 字符buf[std::numeric_limits::max_digits10+1]; std::transform(std::begin(u16s)、std::end(u16s)、buf、, [](char16_t c){return char(c);}); buf[u16s.size()]='\0';//终止符 //这里有错误检查吗? 返回std::strtod(buf,NULL); }
如果您知道您的字符串格式很好(例如没有空格),并且当且仅当性能非常关键时(即,如果您正在解析数百万或数十亿个数字),请不要排除自己解码、在字符串上循环的可能性。查找标准库源代码(可能比较libc++和libstdc++)以了解它们的功能,并对其进行调整。当然,在这些情况下,您还应该注意并行化您的工作,尝试利用SIMD等等。

首先,将utf16数字字符串转换为窄字符串是很简单的。即使您不能确定窄字符集对于7位字符是ASCII,C也保证代码“0”到“9”是连续的,对于Unicode(0x30到0x39)也是如此。因此,代码可以简单到(仅取决于
包含:

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++ = '\0';
    char *end;
    double d = strtod(beg, &end);   // could use better error processing
    delete[] beg;
    return d;
}    
double u16strod(const std::u16string和u16){
char*beg=新字符[u16.size()+1];
char*str=beg;
适用于(char16\u t uc:u16){
if(uc==u“”)*str++='';//对可能的.和空间进行特殊处理
else如果(uc==u'.)*str++=';
否则如果((ucu'9'))中断;//可以使用更好的错误处理
否则{
*str++='0'+(uc-u'0');
}
}
*str++='\0';
字符*结束;
double d=strtod(beg,&end);//可以使用更好的错误处理
删除[]条;
返回d;
}    
如果窄字符集是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++ = '\0';
    char *end;
    double d = strtod(beg, &end);
    delete[] beg;
    return d;
}
double u16strod(const std::u16string和u16){
char*beg=新字符[u16.size()+1];
char*str=beg;
适用于(char16\u t uc:u16){
if((uc=127))break;//只能包含ASCII字符
否则{
*str++=uc;//并且unicode代码是ASCII代码
}
}
*str++='\0';
字符*结束;
双d=strtod(beg和end);
删除[]条;
返回d;
}

我想你是在寻找一些实现它的标准方法,而不是自己编写函数?转换为字符串并使用
std::stof
@Ron,但它不能很快。这并不理想,但你可以编写一个相当快的转换,因为你只有
10个不同的字符要转换。如果你的系统有
16b它
宽字符(如Windows)您可以在(L“1342.223”);在>>d;
中使用
std::wistringstream。但这不会特别快(或可移植)。我会使用
std::string
而不是
new char[]
,然后使用
std::stod()
。使用
std::transform()怎么样
而不是
make_shown()
char buf[max_digits10+1]={};std::transform(u16s.begin(),u16s.end(),buf,[](char16_t ch){return char(ch);};
@RemyLebeau这是个好主意,thnx。