查看本文前先弄清字符编码的大概含义,可点击本链接 本文参考链接 VS编码和文件编码
locale
locale对象封装了一组特定于区域性的功能,程序可以使用这些功能来增强国际可移植性(有关更多信息,请参阅标题<locale>)。
在构建locale对象时,本地化引擎初始化与它关联的所有facets(facet是描述与特定文化方面关联的locale feature的类。),并将其提供给程序。
每个程序都有一个locale对象,这是其全局locale, 默认是 classic locale。可以通过调用locale::global来更改。此全局locale由所有 default-constructed 的locale对象构成。
全局locale还影响C locale(请参阅函数setlocale):当使用locale::global设置新的命名全局locale时,C locale也会被修改。
locale对象可用于访问其关联facet,以使用其格式化功能。它们也可以通过调用流的imbue()成员函数单独注入特定的流对象(如cin、cout或文件流)。
setlocale函数
作用: 设置要由当前程序使用的区域设置信息,更改整个区域设置或部分区域设置。该函数还可用于通过传递NULL作为参数区域设置的值来检索当前区域设置的名称。 区域设置包含有关如何解释和执行某些输入/输出和转换操作的信息,同时考虑到特定的位置和语言设置。 大多数运行环境都有根据用户偏好或本地化设置的某些区域设置信息。但是为了独立于系统区域设置,在开始时,所有C程序都有“C” locale,这是一个相当中立的区域设置,区域设置信息最少,使程序的结果可以预测。为了在环境中使用默认区域设置,可以使用setlocale(LC_ALL,"")。 程序启动时,选择的区域设置是“C”区域设置,与调用setlocale(LC_ALL,“C”) 时设置的区域设置相同。
设置字符编码
C/C++ 语言标准中定义了其运行时的字符编码为 “C” ,“C” 即ASCII 字符集的一个子集,使用setlocale会改变整个应用程序的编码方式。 语法: string setlocale(string category, string locale); 作用: setlocale函数用来配置地域的信息。 参数 category : 官方文档
value | 受影响locale的部分 |
---|
LC_ALL | 整个locale设置。 | LC_COLLATE | 影响strcoll和strxfrm的行为 | LC_CTYPE | 影响字符处理函数(< cctype >的所有函数,除了 isdigit 和 isxdigit),以及多字节和宽字符函数 | LC_MONETARY | 影响localeconv返回的货币格式信息 | LC_NUMERIC | 影响格式化输入/输出操作和字符串格式化函数中的小数点字符,以及localeconv返回的非货币信息 | LC_TIME | 影响strftime的行为 |
参数 locate : 包含C区域设置名称的C字符串。这些是特定于系统的,但至少必须存在以下两个区域设置:
locale name | description |
---|
“C” | Minimal “C” locale | “” | Environment’s default locale |
如果此参数的值为NULL,则函数不会对当前区域设置进行任何更改,但函数仍然返回当前区域设置的名称。
单字符宽字符互相转换
将char转换为wchar_t
mbstowcs函数
语法: size_t mbstowcs (wchar_t* dest, const char* src, size_t max); 作用: 将多字节字符串转换为宽字符字符串 将src指向的多字节序列转换为等效的宽字符序列(存储在dest指向的数组中),直到最大宽字符被翻译或多字节序列src中遇到空字符(该序列也被翻译和存储,但不计入函数返回的长度)。如果成功翻译了最大字符,则存储在dest中的结果字符串不会为空终止。 此函数的行为取决于所选C locate设置的LC_CTYPE类别。 返回值: 写入dest的宽字符数,不包括最终终止的空字符。如果遇到无效的多字节字符,则返回值(size_t)-1。请注意,size_t是unsigned integral 类型,因此可能返回的值都不小于零。 参数dest: dest是指向wchar_t元素数组的指针,它足够长,可以包含生成的序列(最多是最大宽字符)。 参数src: 被解释的多字节序列。多字节序列应以初始移位状态开始。 size_t max: 写入dest的最大wchar_t字符数。Size_t是unsigned integral 类型。
将wchar_t转化为char
wcstombs函数
语法: size_t wcstombs (char* dest, const wchar_t* src, size_t max); 作用: 将宽字符字符串转换为多字节字符串 将src指向的宽字符序列转换为多字节等效序列(存储在dest指向的数组中),直到最大字节被翻译或宽字符转换为空字符。如果成功翻译了最大字节,则存储在dest中的结果字符串不会为空终止。生成的多字节序列以初始移位状态(如果有的话)开始。此函数的行为取决于所选C locate设置的LC_CTYPE类别。
/* wcstombs example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* wcstombs, wchar_t(C) */
int main() {
const wchar_t str[] = L"wcstombs example";
char buffer[32];
int ret;
printf ("wchar_t string: %ls \n",str);
ret = wcstombs ( buffer, str, sizeof(buffer) );
if (ret==32) buffer[31]='\0';
if (ret) printf ("multibyte string: %s \n",buffer);
return 0;
}
输出:
wchar_t string: wcstombs example
multibyte string: wcstombs example
将char转换为wchar_t
mbtowc函数
语法: int mbtowc (wchar_t* pwc, const char* pmb, size_t max); 作用: 将多字节序列转换为宽字符 pmb指向的多字节字符转换为wchar_t类型的值,并存储在pwc指向的位置。该函数返回多字节字符的长度(以字节为单位)。 参数pwc: 指向wchar_t类型的对象的指针。此参数可以是一个空指针,在这种情况下,函数不存储wchar_t翻译,但仍然返回多字节字符的长度(以字节为单位)。 参数pmb: 指向多字节字符的第一个字节的指针。此参数可以是一个空指针,在这种情况下,函数将其内部偏移量重置为初始值,并返回该多字节字符是否具有与状态相关的编码。 max: 多字节字符pmb的最大字节数。在任何情况下,检查的字符不得超过MB_CUR_MAX。 MB_CUR_MAX: 多字节字符的最大大小,此宏扩展到type size_t 的正整数表达式,其值是当前区域设置(类别 LC_CTYPE)的多字节字符中的最大字节数。其值永远不会大于MB_LEN_MAX(见climits)。 返回值: 如果作为pmb传递的参数不是空指针,则返回写入pmb的字符的大小(以字节为单位)。如果没有字符对应关系,则返回-1。如果作为pmb传递的参数是空指针,如果多字节字符编码与状态相关,函数将返回非零值,否则返回零值。
/* mbtowc example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* mbtowc, wchar_t(C) */
void printbuffer (const char* pt, size_t max)
{
int length;
wchar_t dest;
mbtowc (NULL, NULL, 0); /* reset mbtowc */
while (max>0) {
length = mbtowc(&dest,pt,max);
if (length<1) break;
printf ("[%lc]",dest);
pt+=length; max-=length;
}
}
int main()
{
const char str [] = "mbtowc example";
printbuffer (str,sizeof(str));
return 0;
}
Printbuffer按字符打印多字节字符串字符。 输出:
[m][b][t][o][w][c][ ][e][x][a][m][p][l][e]
将wchar_t转化为char
wctomb函数
语法: int wctomb (char* pmb, wchar_t wc); 作用: 将宽字符转换为多字节序列 宽字符wc被转换为多字节,并存储在pmb指向的数组中。该函数返回调用后pmb指向的等效多字节序列的长度(以字节为单位)。 wctomb有自己的内部偏移量,只有通过调用此函数才能根据需要进行更改。pmb使用空指针对函数的调用重置状态(并返回多字节序列是否与状态有关)。此函数的行为取决于所选C locate设置的LC_CTYPE类别。 参数pmb: 指向足以容纳多字节序列的数组的指针。当前区域设置中字符的多字节序列的最大长度为MB_CUR_MAX字节。可以使用空指针调用函数,在这种情况下,函数将其内部移位状态重置为初始值,并返回该多字节字符是否具有与状态相关的编码。 wc: Wchar_t类型的宽字符。 返回值: 如果作为pmb传递的参数不是空指针,则返回写入pmb的字符的大小(以字节为单位)。如果没有字符对应关系,则返回-1。如果作为pmb传递的参数是空指针,如果多字节字符编码与状态相关,函数将返回非零值,否则返回零值。
/* wctomb example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* wctomb, wchar_t(C) */
int main() {
const wchar_t str[] = L"wctomb example";
const wchar_t* pt;
char buffer [MB_CUR_MAX];
int i,length;
pt = str;
while (*pt) {
length = wctomb(buffer,*pt);
if (length<1) break;
for (i=0;i<length;++i) printf ("[%c]",buffer[i]);
++pt;
}
return 0;
}
输出:
[w][c][t][o][m][b][ ][e][x][a][m][p][l][e]
宽、窄字符转换总结
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); //转换单字符串为宽字符串
size_t wcstombs(char *mbstr, const wchar_t *wcstr, size_t count ); //转换宽字符串为单字符串
#include <stdlib.h>
CString str = L"hello";
char sss[20];
wcstombs(sss,str.GetBuffer(),20); //转换宽字符为单字符
// stl 宽字符到 单字符转换
wstring str = L"Hello";
std::wstring::size_type len = str.length();
std::string s(len*2,0);
size_t total = wcstombs(&s[0],str.c_str(),len*2);
s[total] = '/0';
return s;
//mbtowc 和 wctomb 是单个字符相互转换
int len;
setlocale (LC_ALL, "chs"); //设置为简体中文环境
wchar_t wc = L'中';
wprintf(L"1个宽中文字符:%c /n",wc);
char* p = "中";
len = mbtowc (&wc, p, MB_LEN_MAX);
wprintf(L"单字符串转换为1个宽字符:%c 长度: %d/n",wc,len);
char pcmb[MB_LEN_MAX];
len = wctomb (pcmb, wc);
pcmb[len] = 0;
printf("宽字符转换为单字符串:%s 长度:%d/n",pcmb,len);
//utf8 字符串
BYTE utf8[1024];
wchar_t wstr[1024];
char mstr[1024];
//UTF-8转换为宽字符
MultiByteToWideChar( CP_UTF8, 0, utf8,1024, wstr, sizeof(wstr)/sizeof(wstr[0]) );
//宽字符转化为多字节
WideCharToMultiByte( CP_ACP,0,wstr,-1,mstr,1024,NULL,NULL );
注:mbstowcs()是C库函数,要正确的设置Locale才能进行转换,MultiByteToWideChar()是win32函数
为什么使用mbstowcs()一定要调用 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 个。
如果不设置就会出现中文乱码的问题 mbstowcs()与MultiByteToWideChar()的区别 mbstowcs()是MultiByteToWideChar()的简化版,在中文字符的转换上,前者似乎无法对中文字符进行处理,转换后显示成乱码,而后者则不会。
WCHAR strPath[MAX_PATH];
CHAR buf[] = “i am 中国人”;
// 简化版对中文字符的转换不好
// mbstowcs( strPath, buf, MAX_PATH );
// 还是这个比较好
MultiByteToWideChar(CP_ACP, 0, buf, strlen(buf), strPath, MAX_PATH );‘’‘
|