轉(zhuǎn)自http://www.cnblogs.com/moonz-wu/archive/2008/12/30/1365552.html
wprintf 和 wcout
這篇文章應(yīng)該是[netsin]的成果,我勤快,記下來。
注:wprintf是C的標(biāo)準(zhǔn)庫函數(shù),但wcout不是C++的標(biāo)準(zhǔn)成員,C++中的 L"……" 是寬字符,卻未必是unicode字符,這與編譯器實(shí)現(xiàn)相關(guān)。
[乾坤一笑]說:為什么 C/C++ 語言把 L"xx" 定義為由實(shí)現(xiàn)決定的呢?這顯然是為了 C/C++ 的普適性、可移植性。Bjarne 的觀點(diǎn)認(rèn)為,C++ 的方式是允許程序員使用任何字符集作為串的字符類型。另外,unicode 編碼已經(jīng)發(fā)展了若干版本了,是否能永久適合下去也不得而知。有關(guān) unicode 的詳細(xì)論述以及和其它字符集的比較,我推薦你看《無廢話xml》。
以下兩段代碼的執(zhí)行環(huán)境是 windows xp professional 英文版,編譯器是 VS2005RTM。
// C
#include <stdio.h>
#include <locale.h>
int main( void )
{
setlocale( LC_ALL, "chs" );
//setlocale( LC_ALL, "Chinese-simplified" );
//setlocale( LC_ALL, "ZHI" );
//setlocale( LC_ALL, ".936" );
wprintf( L"中國" );
return 0;
}
// C++
#include <iostream>
#include <locale>
using namespace std;
int main( void )
{
locale loc( "chs" );
//locale loc( "Chinese-simplified" );
//locale loc( "ZHI" );
//locale loc( ".936" );
wcout.imbue( loc );
std::wcout << L"中國" << endl;
return 0;
}
說明:別混合使用 setlocale 和 std::locale 。
------------------------- 2006-07-05 記 -------------------------
"VC知識(shí)庫" 編碼為:56 43 D6 AA CA B6 BF E2 00 // ANSI編碼
L"VC知識(shí)庫" 在VC++ 中編碼為:56 00 43 00 E5 77 C6 8B 93 5E 00 00 // (windows口中的unicode)編碼
L"VC知識(shí)庫" 在GCC(Dev-CPP4990) 中編碼為:56 00 43 00 D6 00 AA 00 CA 00 B6 00 BF 00 E2 00 00 00 // 只是將ANSI編碼簡單的加0
L"VC知識(shí)庫" 在GCC(Dev-CPP4992) 中編譯失敗,報(bào) Illegal byte sequence
L"VC知識(shí)庫" 在 Dev-CPP4992 中解決步驟為:
a. 將文件保存為 utf-8 編碼 // utf-8 是unicode的其中一種,但和(windows口中的unicode)不一樣
b. 去掉BOM頭:用二進(jìn)制編輯器(比如VC)去掉剛才utf-8文件的前三個(gè)字節(jié) // Linux/UNIX并不使用BOM
c. 使用 gcc/g++ 編譯運(yùn)行
經(jīng)過以上解決步驟,在 dev-cpp4992 中
"VC知識(shí)庫" 編碼為: 56 43 E7 9F A5 E8 AF 86 E5 BA 93 00 // utf-8編碼,注意不再是ANSI編碼了,因此用 printf/cout 將輸出亂碼
L"VC知識(shí)庫" 編碼為: 56 00 43 00 E5 77 C6 8B 93 5E 00 00 // (windows口中的unicode)編碼
補(bǔ)充:在mingw32中使用wcout和wstring需要加一些宏,比如
#define _GLIBCXX_USE_WCHAR_T 1
#include <iostream>
int main( void )
{
std::wcout << 1 << std::endl;
}
可以編譯通過,但無法Link通過,在網(wǎng)上google了一下,stlport說mingw32有問題,mingw32說是M$的c runtime有問題。
------------------------- 2007-01-05 記 -------------------------
一個(gè)多字節(jié)字符串和寬字符字符串互相轉(zhuǎn)化的事例
#define _CRT_SECURE_NO_WARNINGS // only for vc8
#include <string>
#include <clocale>
#include <cassert>
inline const std::string to_mbcs( const std::string& src )
{
return src;
}
const std::string to_mbcs( const std::wstring& src )
{
char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) ); // 保存原來的locale
setlocale( LC_CTYPE, "chs" ); // 設(shè)置當(dāng)前l(fā)ocale為chs,這在非簡體中文平臺(tái)上不可缺少
size_t count1 = wcstombs( NULL, src.c_str(), 0 ); // 計(jì)算新字符串長度
std::string des( count1, ' ' );
size_t count2 = wcstombs( &des[0], src.c_str(), count1 ); // 轉(zhuǎn)化
assert( count1 == count2 );
setlocale( LC_CTYPE, old_locale ); // 恢復(fù)到原來的locale
free( old_locale );
return des;
}
inline const std::wstring to_wcs( const std::wstring& src )
{
return src;
}
const std::wstring to_wcs( const std::string& src )
{
char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) ); // 保存原來的locale
setlocale( LC_CTYPE, "chs" ); // 設(shè)置當(dāng)前l(fā)ocale為chs,這在非簡體中文平臺(tái)上不可缺少
size_t count1 = mbstowcs( NULL, src.c_str(), 0 ); // 計(jì)算新字符串長度
std::wstring des( count1, L' ' );
size_t count2 = mbstowcs( &des[0], src.c_str(), count1 ); // 轉(zhuǎn)化
assert( count1 == count2 );
setlocale( LC_CTYPE, old_locale ); // 恢復(fù)到原來的locale
free( old_locale );
return des;
}
#include <iostream>
int main( void )
{
using namespace std;
cout << to_mbcs("你好1") << endl;
cout << to_mbcs(L"你好2") << endl;
const locale loc( "chs" );
wcout.imbue( loc );
wcout << to_wcs("你好3") << endl;
wcout << to_wcs(L"你好4") << endl;
}
------------------------- 2008-09-03 記 -------------------------
參見 《MBCS To Unicode 》