如何在不使用平台特定功能的情况下打印UTF-8字符串?

如何在不使用平台特定功能的情况下打印UTF-8字符串?,utf-8,locale,cout,multiplatform,wstring,Utf 8,Locale,Cout,Multiplatform,Wstring,是否可以在不使用平台特定功能的情况下打印UTF-8字符串 #include <iostream> #include <locale> #include <string> using namespace std; int main() { ios_base::sync_with_stdio(false); wcout.imbue(locale("en_US.UTF-8")); // broken on Windows (?) wst

是否可以在不使用平台特定功能的情况下打印UTF-8字符串

#include <iostream>
#include <locale>
#include <string>

using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);
    wcout.imbue(locale("en_US.UTF-8")); // broken on Windows (?)

    wstring ws1 = L"Wide string.";
    wstring ws2 = L"Wide string with special chars \u20AC";  // Euro character

    wcout << ws1 << endl;
    wcout << ws2 << endl;
    wcout << ws1 << endl;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
ios_base::与_stdio同步(false);
wcout.imbue(locale(“en_US.UTF-8”);//在Windows上损坏(?)
wstring ws1=L“宽字符串。”;
wstring ws2=L“带特殊字符的宽字符串\u20AC”;//欧元字符

在Windows的一个MIW环境中,我还没有使用GCC,但从我收集到的它不支持C++语言环境。

因为它不支持C++区域,这不是真正相关的,但是FIY,Windows不使用与大多数其他平台相同的区域命名方案。它们使用相似的语言.CalpUn.Cuffice,但是语言和国家不是代码,编码是Windows代码页号。因此,区域将是“EngLex.U.S. 65001”。但是,这不是一个受支持的组合(任何语言环境都不支持代码页65001(UTF-8))

之所以只打印
ws1
,而且只打印一次,是因为当打印字符
\u20AC
时,流失败并且设置了失败位。您必须先清除错误,然后才能打印进一步的内容


C++11引入了一些可移植处理UTF-8的功能,但并不是所有功能都受支持,而且添加的功能并不能完全解决问题。但目前的情况如下:

当VS中支持
char16_t
char32_t
作为本机类型而不是typedef时,您将能够使用标准的codecvt方面的专门化
codecvt
codecvt
,它们分别需要在UTF-16或UTF-32与UTF-8之间转换(而不是执行字符集或系统编码)。这还不起作用,因为在当前的VS(和VS11DP)中,这些类型只是typedef,模板专门化在typedef上不起作用,但代码已经在VS2010的头中,只是在
ifdef
后面进行保护

该标准还定义了一些受支持的特殊用途codecvt方面模板,codecvt_utf8和codecvt_utf8_utf16。前者根据所使用的宽字符类型的大小在UTF-8和UCS-2或UCS-4之间进行转换,后者在UTF-8和UTF-16代码单元之间进行转换,与宽字符类型的大小无关体育

std::wcout.imbue(std::locale(std::locale::classic(),new std::codecvt_utf8_utf16<wchar_t>()));
std::wcout << L"ØÀéîðüýþ\n";
以上内容仍然不太便于移植,因为它假设wchar_t是UTF-16,这在Windows上是如此,但在大多数其他平台上不是如此,而且该标准也不要求它。(事实上,我的理解是,它在技术上不符合要求,因为UTF-16需要多个代码单元来表示某些字符,而标准要求所选编码中的所有字符都必须可以在单个wchar_____t中表示)


或者,如果您的编码标准允许使用宏,则只需使用预处理器宏来定义适当的typedef。

Windows对UTF-8的支持非常差,虽然可以使用Windows API来实现,但一点也不有趣,而且,您的问题指出您不想使用特定于平台的函数

至于在“标准C++”中执行,我不确定在Windows下是否可以不使用特定于平台的代码。但是,有许多第三方库可用,它们将抽象出这些平台细节,并允许您编写可移植代码

在Boost.Locale库的帮助下,我最近更新了我的应用程序,在内部使用UTF-8。

它的locale生成类将允许您生成基于UTF-8的locale对象,然后您可以将该对象嵌入到所有标准流中


我现在通过MinGW-w64在MSVC和GCC下成功地使用了它!我强烈建议您检查一下。是的,不幸的是,它在技术上不是“标准C++”,但是Boost几乎无处不在,实际上是一个事实上的标准,所以我不认为这是一个很大的问题。

感谢您的详细解释!我们我认为Boost是标准的一部分,你知道明W32有什么问题吗?
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
puts(convert(L"ØÀéîðüýþ\n).to_bytes().c_str());
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert;
std::wstring_convert<
    std::conditional<sizeof(wchar_t)==2,std::codecvt_utf8_utf16<wchar_t>,
                                        std::codecvt_utf8<wchar_t>
    >::type,
    wchar_t
> convert;