[返回首页] - [索引页面] - [文章列表]

 

主题:关于用C++标准库中的locale将汉字由multibytes转换到unicode的一个小问题



vc7.1中的一个问题

// 我用的是中文版的Windows2000 Professional
locale langLocale("");

// 所以下面这行输出:Chinese_People's Republic of China.936
cout << langLocale.name() << endl;

char narrow[] = "你好hello";

// 下面这行输出:你好hello
cout << narrow << endl;

wchar_t wide[100];
// 用这个Chinese_People's Republic of China.936的locale把
// "你好hello"变成宽字符的
use_facet<ctype<wchar_t> >(langLocale).widen(narrow, narrow + 9, wide);
wide[strlen(narrow)] = L'\0';

// 输出是:hello 竟然没有你好两个字了,调试器观察,那两个字全是0xffff
wcout << wide << endl;


怎么回事?库的错误?跟踪到函数_Dowiden,它又调用了_Mbrtowc
可是_Mbrtowc没有源码啊,显示源码在
f:\vs70builds\3077\vc\crtbld\crt\src\xmbtowc.c
靠!这路径好像是在开发visual studio哦
我的机子可没有f盘,想必是在微软某个家伙的机子上了。

怎么办?


回复人:freefalcon(心宇—小小菜鸟想高飞)  两星(中级)  信誉:100      2004-9-2 18:19:23  得分:5

没用过use_facet

帮你up
TOP
回复人:plainsong(短歌)  两星(中级)  信誉:197      2004-9-2 18:23:22  得分:5

C++缺省的local恐怕不支持GB码吧?对这部分不熟悉,不知道GB字符集的local名字是什么。
TOP
回复人:CNXQS(天堂神曲(什么都不会,真无奈))  二级(初级)  信誉:100      2004-9-2 21:22:16  得分:5

看不懂啊,帮你顶了
TOP
回复人:keiy()  一星(中级)  信誉:100      2004-9-2 22:05:26  得分:5

没用过vc7.1,一直用vc6.0,它的WideCharToMultiByte/MultiByteToWideChar
很好用
TOP
回复人:shornmao(毛豆子[死猫])  一星(中级)  信誉:120      2004-9-2 22:45:49  得分:5

字符集编码的转换,标准库只定义了接口,而没有提供实现,你需要自己提供
TOP
回复人:rorot(我的猫儿)  一星(中级)  信誉:79      2004-9-3 0:29:29  得分:5

try to use std::wcout.imbue( std::locale ( "ZHI" ) );


TOP
回复人:iBear(大熊 不要怀疑我的温柔)  一级(初级)  信誉:100      2004-9-3 11:52:11  得分:5

WideCharToMultiByte/MultiByteToWideChar
是win32的api,不是标准库里的东西

TOP
回复人:goboo(高冉)  一级(初级)  信誉:100      2004-9-3 12:43:15  得分:5

帮你找找
TOP
回复人:rorot(我的猫儿)  一星(中级)  信誉:79      2004-9-3 21:51:23  得分:45

我的locale是zh_CN.GBK, 使用了你的ctype::widen(...)函数解析后查看了内存里是有内容的. 不过依然不能std::wcout << L"sdf地方"; ... 但是考虑到ctype::widen(...)转换的只是基本源字符里的96个标准字符, 所以我采用了codecvt<wchar_t, char, mbstate_t>::in(...)来转换.. 由于locale命名不标准, 我找不到在linux下的适当locale对象. 所以希望借助于win32的locale("ZHI")来测试...这里我贴的代码只是一个测试,不一定能解决你的问题, 希望楼主把解决的最终方案挂上来.

下面的代码希望有热心人在 VC7.0 下测试(不能使用VC6, DEV++), 把结果贴上来....
//------------------------------------
#include <iostream>
#include <locale>
#define DEBUG

int main( int argc, char** argv )
{
char narrow[] = "China中国";
wchar_t *word = new wchar_t[100];
const char *from, *nstart = narrow;
wchar_t *to = NULL, *wstart = word;
mbstate_t cs;
try
{
#ifdef WIN32
std::locale lang("ZHI");
#else
std::locale lang("POSIX");
#endif
std::use_facet< std::codecvt<wchar_t, char, mbstate_t> >(lang).in(cs, nstart, nstart+strlen(narrow), from, wstart, wstart+100, to );

#ifdef DEBUG
std::wstring s(word);
std::cout << "s.size(): " << s.size() << std::endl;
const size_t size_ = s.size()*sizeof(wchar_t);
char* ptr = (char*) word;
for (int i=0; i<size_; ++i )
std::cout << static_cast <int> (*(ptr+i)) << " ";
std::cout << std::endl;
#endif
std::wcout.imbue (lang);
std::wcout << word << std::endl;
delete[] word;
}
catch ( std::exception &e )
{
std::cerr << e.what() << "\n";
}
return 0;
}
TOP
回复人:duyanning(狗见愁)  一级(初级)  信誉:100      2004-9-4 22:07:51  得分:0

#include <locale>
#include <iostream>

using namespace std;

int main( )
{
char narrow[] = "你好hello";

wchar_t wide[100];
memset(wide, 0, sizeof wide);

char* pszNext;
wchar_t* pwszNext;
mbstate_t state;

// locale loc("chs_china.936"); // 失败!
// locale loc(""); // 还是失败!这和上面那行效果一样,我用的是中文简体w2k pro
locale loc("C"); // 成功!竟然是这个默认的C locale

cout << loc.name() << endl;

use_facet<codecvt<wchar_t, char, mbstate_t> >(loc).in(
state,
narrow, narrow + strlen(narrow), pszNext,
wide, wide + strlen(narrow), pwszNext
);

wcout << wide << endl;

return EXIT_SUCCESS;
}

--------------------------------
我觉得还是不合适啊,竟然是这个C locale???大家再发表一下看法嘛
TOP
回复人:rorot(我的猫儿)  一星(中级)  信誉:79      2004-9-4 22:53:16  得分:5

"C"是US_ASCII的locale, 非国际化程序的默认方式. 你很幸运, 能在win32的支持下成功.

这里有专门介绍locale的内容
http://www.roguewave.com/support/docs/sourcepro/stdlibref/2-6.html
这里是一个multibytes2unicode使用facet的例子
http://www.roguewave.com/support/docs/sourcepro/stdlibug/40-5.html
TOP
回复人:duyanning(狗见愁)  一级(初级)  信誉:100      2004-9-5 10:26:36  得分:0

用C locale,vc7.1搭配STLport-4.6.2也成功了;但是,若改用locale loc("CHS_CHN")会失败。"CHS_CHN"是在STLport-4.6.2\src\c_locale_win32\c_locale_win32.c中查到的。
TOP
回复人:duyanning(狗见愁)  一级(初级)  信誉:100      2004-9-5 10:43:46  得分:0

但是,这不合适呀!如果"你好hello"即"\xc4\xe3\xba\xc3\x68\x65\x6c\x6c\x6f"是在保存在一个文件中的,那么上面这段程序在简体版的win2k和繁体版的win2k上运行势必有着不同的结果,而他们处理的却是完全一样的内容。
TOP
回复人:yjh1982(血精灵)  一星(中级)  信誉:105      2004-9-20 15:24:09  得分:5

mark
TOP
回复人:daylove(痴迷C++)(初级阶段-----在我没升四叉之前绝不灌水)  三级(初级)  信誉:100      2004-9-21 17:17:38  得分:5

看来我只能顶了,学习一下
TOP


该问题已经结贴 ,得分记录:freefalcon(5)、plainsong(5)、CNXQS(5)、keiy(5)、shornmao(5)、rorot(5)、iBear(5)、goboo(5)、rorot(45)、rorot(5)、yjh1982(5)、daylove(5)、