IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 宽、窄字符转换 -> 正文阅读

[C++知识库]C++ 宽、窄字符转换

查看本文前先弄清字符编码的大概含义,可点击本链接
本文参考链接
VS编码和文件编码

locale

locale对象封装了一组特定于区域性的功能,程序可以使用这些功能来增强国际可移植性(有关更多信息,请参阅标题<locale>)。

在构建locale对象时,本地化引擎初始化与它关联的所有facets(facet是描述与特定文化方面关联的locale feature的类。),并将其提供给程序。

每个程序都有一个locale对象,这是其全局locale, 默认是
classic
locale。可以通过调用locale::global来更改。此全局locale由所有 default-constructedlocale对象构成。

全局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 namedescription
“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 );‘’‘
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:10:05  更:2022-02-28 15:13:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:59:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码