如何在不使用mbstowcs的情况下在C++中将ASCII char*转换为wchar_t*

How to convert ASCII char* to wchar_t* in C++ without using mbstowcs?

本文关键字:ASCII char 转换 wchar 中将 C++ mbstowcs 情况下      更新时间:2023-10-16

我想在Linux上的C++中将ASCII字符*转换为wchar_t*,而不使用mbstowcs()。在iOS和Windows上,这非常有效。然而,在安卓系统上,mbstowcs似乎可以一对一地转换事物。即使使用setlocale()的不同变体,我也无法成功转换。

我可能会在Android上手动转换它,复制1个字节,然后用零填充其余部分。但这适用于ASCII吗?UTF-32/Unicode的前255个字符是否与ASCII(ISO 8859-1/ISO Latin-1)字符集相同?

让思考更清晰:

  • ASCII是一种使用0..127的值对单个字符进行编码的字符
  • Latin-1是另一个字符集,它通过使用128.255的值来编码自己的字符来扩展ASCII

事实上,大多数体系结构字节是8位,所以在字节中存储ASCII字符时仍然有128个值可用。因此,设计了几个不同的字符集来扩展128到255的ASCII值。Happy事故,被称为Latin-1的代码被用于Unicode中的前256个代码点(如BoBTFish所指出的)。因此,如果你一方面有一个使用Latin-1编码的字符串,你只需将每个值分配给一个wchar_t(这将确保架构中的端序正确"零填充"),它将是一个对应于相同字符的unicode代码点的有效wstring。然后,wstring的使用者必须将其内容解释为unicode代码点。

此外,一旦你不能保证原始字符串的编码是Latin-1,你就会遇到问题。(例如,UTF-8编码不是将每个字节映射到Latin-1)。

如果您不介意使用STL依赖项并使用stringwstring而不是原始char *wchar_t *指针,则可以使用以下函数来执行字符串转换:

template<typename TARGET, typename SOURCE>
TARGET convertString(const SOURCE &s)
{
    TARGET result;
    result.assign(s.begin(), s.end());
    return result;
}

按如下方式使用:

#include <string>
#include <iostream>
using namespace std;
int main()
{
    wstring wstr(L"HELLO WORLD");
    string str(convertString<string, wstring>(wstr));
    cout << str << endl;
    return 0;
}

这将执行逐个字符的转换,并且与平台无关。这已经在使用GCC 4.7.3和Visual C++2012的Windows上进行了测试,在使用GCC 4.73的Linux上也进行了测试。

使用std::wstring_convert:可以缩短以下代码

#include <string>
#include <locale>
std::string convert(std::wstring str, std::locale loc = std::locale(),
                                             std::mbstate_t state = std::mbstate_t())
{
    const wchar_t* a; char *b;
    std::string res;
    res.resize(str.size());
    auto bytes = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc)
        .out(state, &str[0], &str[str.size()], a, &res[0], &res[res.size()], b);
    return res;
}
int main()
{
    std::wstring a = L"abcdef";
    std::string b = convert(a);
}

演示