几何尺寸与公差论坛

 找回密码
 注册
查看: 3318|回复: 2

vc字符编码转换解决方案

[复制链接]
发表于 2007-8-31 13:07:01 | 显示全部楼层 |阅读模式
利用c或者vc编写程序的过程中免不了要做一些字符的转化,比较常见的有从ANSI到UNICODE,或者从UNICODE到ANSI,如何做这样的转换呢?结合笔者的经验,暂时提供两种比较常见的方法,以及各个方法需要注意的问题
(1)标准c中的转换
可以调用mbstowcs函数
函数原型为:size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count );
头文件为:<stdlib.h>
所支持的操作系统为:ANSI, Win 95, Win NT
在使用这个函数做转换时需要注意的是对于非英语为本地语言的国家和地区,在使用之前要调用setlocale函数,否则转换出来的字符可能不是用户希望得到的结果。
setlocale:
函数原形为:char *setlocale( int category, const char *locale );
头文件:<locale.h>
所支持的操作系统为:ANSI, Win 95, Win NT
对于简体中文可以使用如下设置:setlocale( LC_ALL, "chs" );

为什么一定要调用setlocale呢?
因为在C/C++语言标准中定义了其运行时的字符集环境为"C",也就是ASCII字符集的一个子集,那么mbstowcs在工作时会将cstr中所包含的字符串看作是ASCII编码的字符,而不认为是一个包含有chs编码的字符串,所以他会将每一个中文拆成2个ASCII编码进行转换,这样得到的结果就是会形成4个wchar_t的字符组成的串,那么如何才能够让mbstowcs正常工作呢?在调用mbstowcs进行转换之间必须明确的告诉mbstowcs目前cstr串中包含的是chs编码的字符串,通过setlocale( LC_ALL, "chs" )函数调用来完成,需要注意的是这个函数会改变整个应用程序的字符集编码方式,必须要通过重新调用setlocale( LC_ALL, "C" )函数来还原,这样就可以保证mbstowcs在转换时将cstr中的串看作是中文串,并且转换成为2个wchar_t字符,而不是4个。(注:这段内容转自网络,谢谢chemz)

(2)vc中的转换
可以调用MultiByteToWideChar函数
函数原型为:
int MultiByteToWideChar(
UINT CodePage, // code page
DWORD dwFlags, // character-type options
LPCSTR lpMultiByteStr, // address of string to map
int cchMultiByte, // number of bytes in string
LPWSTR lpWideCharStr, // address of wide-character buffer
int cchWideChar // size of buffer
);
Header: Declared in winnls.h.
Import Library: Use kernel32.lib.
在使用MultiByteToWideChar函数时需要注意的是:CodePage项可以填CP_ACP或者其他豫定义的字符集(CP_ACP比较常用),dwFlags项填MB_PRECOMPOSED比较常见,需要特别注意的是cchWideChar项最好不要使用wcslen函数计算来得到,因为好多人习惯于在使用变量前先将变量初始化为0(这也是一个很好的编程习惯,可以避免一些不必要的错误),但如果先memset为0,然后再wcslen的话,则MultiByteToWideChar返回已经转换了多少字符,但因为指定的cchWideChar为0,所以不对lpWideCharStr做任何操作,这一点要特别注意,免得出现不必要的错误。

综合以上两种方法,可以说MultiByteToWideChar是mbstowcs的增强版。

附录:
这里的codepage在MSDN定义如下

Bit Code page Description
ANSI
0 1252 Latin 1
1 1250 Latin 2: Eastern Europe
2 1251 Cyrillic
3 1253 Greek
4 1254 Turkish
5 1255 Hebrew
6 1256 Arabic
7 1257 Baltic
8 1258 VietNam
9 - 15 Reserved for ANSI
ANSI and
OEM
16 874 Thai
17 932 Japanese, Shift-JIS
18 936 Chinese: Simplified chars—PRC and Singapore
19 949 Korean Unified Hangeul Code (Hangeul TongHabHyung Code)
20 950 Chinese: Traditional chars—Hong Kong SAR, PRC and Taiwan
21 1361 Korean (Johab)
22 - 29 Reserved for alternate ANSI and OEM
30 - 31 Reserved by system.
OEM
32 - 46 Reserved for OEM
47 1258 VietNam
48 869 IBM Greek
49 866 MS-DOS Russian
50 865 MS-DOS Nordic
51 864 Arabic
52 863 MS-DOS Canadian French
53 862 Hebrew
54 861 MS-DOS Icelandic
55 860 MS-DOS Portuguese
56 857 IBM Turkish
57 855 IBM Cyrillic; primarily Russian
58 852 Latin 2
59 775 Baltic
60 737 Greek; former 437 G
61 708 Arabic; ASMO 708
62 850 Western European/Latin 1
63 437 US

setlocal 时也可使用如下方式
// 运行时设定当前 ANSI 编码,VC 格式
setlocale(LC_ALL, ".936");
其中.936中的936即是上面的codepage号

// GCC 中格式
setlocale(LC_ALL, "zh_CN.GBK");
 楼主| 发表于 2007-9-7 14:20:33 | 显示全部楼层

回复: vc字符编码转换解决方案

#pragma setlocale(".437")
#pragma setlocale(LC_ALL, "english")
#pragma setlocale(LC_ALL, "english")
发表于 2009-10-9 13:00:34 | 显示全部楼层

回复: vc字符编码转换解决方案

关于不同制式时间格式问题//欧洲,中国,美国
System.DateTime.Now得到系统当前时间,格式如下:(时间只是举例)      
  中国     2004/11/16     22:51:12      
  美国     11/16/2004     22:51:12      
  欧洲     16/11/2004     22:51:12      
      
  把这个时间插入到数据库中时间字段时遇到如下麻烦问题:      
  可以接收中国和美国时间(sqlServer支持这个两个时间格式),但是不接收欧洲这个时间格式,会把16当作月份处理,所以程序会抛出月份超出范围的错误。      
  用DateTime.ToShortDate()得到的也是16/11/2004      
  请教:如何能让数据库接受这个欧洲制式的时间格式,或者有什么更妙的解决方法,在此小弟先谢了。      
      
  我最笨的方法就是用      
  datetime.year.tostring()+"-"     +     datetime.month.tostring()     +     "-"     +datetime.day.tostring()      
  组成字符串再转成中国制式的时间格式。      
  注:程序是在国内开发,在欧洲使用。没有这方面的经验,请教各位!
http://topic.csdn.net/t/20041116/23/3559521.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|几何尺寸与公差论坛

GMT+8, 2024-5-10 16:02 , Processed in 0.084484 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表