C++ 如何打印C++;wstring UTF-8字符到Mac OS或Unix终端?
如何使用C++ 如何打印C++;wstring UTF-8字符到Mac OS或Unix终端?,c++,macos,unicode,C++,Macos,Unicode,如何使用std::wcout打印std::wstring 我尝试了以下建议,但它仅适用于打印此“Hola但不是此日本: #include <iostream> #include <clocale> int main(int argc, char* argv[]) { char* locale = setlocale(LC_ALL, ""); std::cout << "locale: " << locale << std::
std::wcout
打印std::wstring
我尝试了以下建议,但它仅适用于打印此“Hola代码>但不是此日本代码>:
#include <iostream>
#include <clocale>
int main(int argc, char* argv[])
{
char* locale = setlocale(LC_ALL, "");
std::cout << "locale: " << locale << std::endl; // "C" for me
std::locale lollocale(locale);
setlocale(LC_ALL, locale);
std::wcout.imbue(lollocale);
std::wcout << L"¡Hola!" << std::endl; // ok
std::wcout << L"日本" << std::endl; // empty :(
return 0;
}
根据libstdc++上的多个bug报告(例如),在C运行时和libstdc++之间存在令人讨厌的交互,似乎没有人急于尝试修复它,可能是因为utf-8在大多数情况下“只起作用”
错误报告提到了两种解决方法,使用ios_base::sync_with_stdio(false)
或locale::global(…)
根据libstdc++上的多个错误报告(例如),在C运行时和libstdc++之间存在令人讨厌的交互,似乎没有人愿意尝试修复它,可能是因为utf-8“刚刚工作”在大多数情况下
bug报告提到了两种解决方法,使用ios\u base::sync\u with\u stdio(false)
或locale::global(…)
打印wstring的方法是将其转换为基于UTF-8字符的字符串。严重地脱离了Windows或其他各种平台库,不幸的是,这些平台库在意识到这是一个多么糟糕的想法之前就采用了wchar\t
// move to clang and libc++ then
#include <codecvt>
int main(){
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert; // converts between UTF-8 and UCS-4 (given sizeof(wchar_t)==4)
std:wstring s = L"日本";
std::cout << convert.to_bytes(s);
}
另外,如果您使用libstdc++,您应该知道它在OS X上不支持正确的区域设置。您必须使用libc++才能使OS X的区域设置名称(例如,“en_US.UTF-8”)正常工作。打印wstring的方法是将其转换为基于UTF-8字符的字符串。严重地脱离了Windows或其他各种平台库,不幸的是,这些平台库在意识到这是一个多么糟糕的想法之前就采用了wchar\t
// move to clang and libc++ then
#include <codecvt>
int main(){
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert; // converts between UTF-8 and UCS-4 (given sizeof(wchar_t)==4)
std:wstring s = L"日本";
std::cout << convert.to_bytes(s);
}
此外,如果您使用的是libstdc++,您应该知道它在OS X上不支持正确的区域设置。您必须使用libc++才能使OS X的区域设置名称(例如,“en_US.UTF-8”)正常工作。使用nowide库以最简单的方式转换为UTF-8。然后,使用常规printf。使用nowide库以最简单的方式转换为UTF-8。然后,使用常规printf。默认编码:
- Windows UTF-16
- Linux UTF-8
- MacOS UTF-8
我的解决方案步骤,包括空字符\0(避免截断)。不使用windows.h标题上的函数:
添加宏以检测平台。
Windows/Linux及其他
创建函数,将std::wstring转换为std::string,并将std::string反向转换为std::wstring
创建打印功能
打印std::string/std::wstring
检查。原始字符串后缀
Linux代码。使用std::cout直接打印std::string,Linux上的默认编码是UTF-8,不需要额外的函数
在Windows上,如果需要打印unicode。我们可以使用std::wstring打印unicode字符
最后在Windows上。您需要在控制台中对unicode字符提供强大且完整的视图支持。
我推荐
QA
- 使用VC++在Microsoft Visual Studio 2019上测试;std=c++17。(Windows项目)
- 使用Clang编译器在repl.it上进行测试;std=c++17
Q.为什么不使用
头函数和类?
A.反对在VC++上不可能构建,但在g++上没有问题。我更喜欢零警告和头痛
Q.std::wstring是跨平台的?
A.No.std::wstring使用wchar\t元素。在Windows wchar\U t上,大小为2字节,每个字符以UTF-16单位存储,如果字符大于U+FFFF,则字符以两个UTF-16单位(2个wchar\U t元素)表示,称为代理项对。在Linux上,wchar\u t大小为4字节,每个字符存储在一个wchar\u t元素中,不需要代理项对。检查
Q.std::string是跨平台的吗?
是的。string使用char元素。在大多数编译器中,保证字符类型的字节大小相同。字符类型大小为1字节。检查
完整示例代码
#包括
#包括
#包括
#包括
//窗户
#如果(_WIN32)
#包括
#包括
#定义WINDOWS\u平台1
#定义DLLCALL STDCALL
#定义DLLIMPORT _declspec(DLLIMPORT)
#定义DLLEXPORT\u declspec(DLLEXPORT)
#定义DLLPRIVATE
#定义NOMINMAX
//EMSCRIPTEN
#已定义的elif(_EMSCRIPTEN__;)
#包括
#包括
#包括
#包括
#定义EMSCRIPTEN_平台1
#定义DLLCALL
#定义DLLIMPORT
#定义DLLEXPORT属性(可见性(“默认”))
#定义DLLPRIVATE属性(可见性(“隐藏”))
//LINUX-Ubuntu、Fedora、Centos、Debian、RedHat
#elif(uuLinux_uu124; u124; uuGNU_124; u124; 124; u124; 124; 124; 124; LINUX | | LINUX)
#定义LINUX_平台1
#包括
#包括
#定义DLLCALL-CDECL
#定义DLLIMPORT
#定义DLLEXPORT属性(可见性(“默认”))
#定义DLLPRIVATE属性(可见性(“隐藏”))
#定义CoTaskMemAlloc(p)malloc(p)
#定义CoTaskMemFree(p)free(p)
//安卓
#elif(安卓安卓)
#定义ANDROID_平台1
#定义DLLCALL
#定义DLLIMPORT
#定义DLLEXPORT属性(可见性(“默认”))
#定义DLLPRIVATE属性(可见性(“隐藏”))
//马科斯
#已定义的elif(_苹果公司)
#包括
#包括
#定义DLLCALL
#定义DLLIMPORT
#定义DLLEXPORT属性(可见性(“默认”))
#定义DLLPRIVATE属性(可见性(“隐藏”))
#包括“TargetConditionals.h”
#如果目标IPHONE和目标IPHONE模拟器
#定义IOS_模拟器_平台1
#elif TARGET_OS_IPHONE
#定义IOS_平台1
#elif TARGET_OS_MAC
#定义MACOS_平台1
#否则
#恩迪夫
#恩迪夫
typedef std::string字符串;
类型定义标准::wstring wstring;
#定义空字符串u8“s
#定义空字符串
使用名称空间std::literals::string_literals;
类字符串
{
公众:
静态字符串宽字符串缩放(常量wstr和wstr)
{
如果(wstr.empty
// move to clang and libc++ then
#include <codecvt>
int main(){
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert; // converts between UTF-8 and UCS-4 (given sizeof(wchar_t)==4)
std:wstring s = L"日本";
std::cout << convert.to_bytes(s);
}
char* locale = setlocale(LC_ALL, "");
std::cout << "locale: " << locale << std::endl; // "C" for me
std::wcout.imbue(std::locale("en_US.UTF-8"));
std::wcout << L"¡Hola!\n";
std::wcout << L"日本\n";