2012-07-16 99 views
2

如何使用std::wcout打印std::wstring如何将C++ wstring UTF-8字符打印到Mac OS或Unix终端?

我尝试以下,这是推荐here,但它仅适用于打印此¡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; 
} 

还有以下(这是推荐here)不会在打印日文字符全部:

#include <stdio.h> 
#include <string> 
#include <locale> 
#include <iostream> 

using namespace std; 

int main() 
{ 

     std::locale::global(std::locale("")); 
     wstring japan = L"日本"; 
     wstring message = L"Welcome! Japan is "; 

     message += japan; 

     wprintf(message.c_str()); 
     wcout << message << endl; 
} 

所有这些都在Mac OS 10.6.8上。使用g ++ 4.2.1,使用终端2.1.2。

终端一般可以显示字符,例如当我的源代码为cat时。此外,这个命令工作正常cout << "日本" << std::endl;,但我确实需要打印wstring

$LANG是这样的:

$ echo $LANG 
en_US.UTF-8 
+0

这不会有帮助,但这里是Mac OSX的猫的源代码:http://www.freebsd.org/cgi/cvsweb.cgi/src/bin/cat/cat.c?rev= 1.33.2.1.8.1; content-type = text%2Fx-cvsweb-markup – Wug 2012-07-16 21:19:32

+1

'wstring'不会是UTF-8。希望你的编译器将UTF-8源码转换为宽字符常量。 – 2012-07-16 21:22:58

+0

也许这个问题很有用http://stackoverflow.com/questions/148403/utf8-to-from-wide-char-conversion-in-stl – 2012-07-16 21:46:39

回答

4

据对的libstdc多个bug报告++(如http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35353),还有C运行时和libstdC++之间讨厌的相互作用,并似乎没有人渴望尝试修复它,可能是因为utf-8在大多数情况下“正常工作”。

该错误报告提到了两种解决方法,使用ios_base::sync_with_stdio(false)locale::global(...)

5

打印wstring的方式是将其转换为基于UTF-8字符串的字符串。严重的是在Windows之外的wchar_t is pointless或其他各种其他平台库之一,不幸在采用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); 
} 

而只是为了解释什么错在你展示的代码;

char* locale = setlocale(LC_ALL, ""); 
std::cout << "locale: " << locale << std::endl; // "C" for me 

此处的语言环境字符串是应用更改后的语言环境名称。既然你说你得到“C”,这意味着你正在使用“C”语言环境。通常人们会得到一个像“en_US.UTF-8”这样的名字,但无论出于何种原因,您的环境没有正确设置。您显示$LANG设置正确,但其中一个其他语言环境变量设置不同。

在任何情况下,您都使用“C”语言环境,它只需要支持基本字符集。我相信OS X会得到的行为是,任何char将直接转换为相同的wchar_t值,并且char支持范围内的值只有wchar_t会转换回来。这与使用基于ISO 8859-1的区域设置实际上是相同的,所以日文字符将不起作用。


如果你真的坚持要根据本区域东西然后去工作,你需要得到一个相应的语言环境,一个使用UTF-8。您可以找出您的环境出了什么问题,或者您可以使用不可移植的显式区域名称。

std::wcout.imbue(std::locale("en_US.UTF-8")); 
std::wcout << L"¡Hola!\n"; 
std::wcout << L"日本\n"; 

另外,如果你使用的libstdC++,你应该知道,它不支持正确的语言环境在OS X上你必须为了使用的libC++的OS X的区域名称(例如,“EN_US。 UTF-8“)工作。

0

使用nowide库以最简单的方式转换为UTF-8。然后,使用普通的printf。