c++中的字符集与中文(宽字符)

  首先要来说一说字符集和编码的关系,这两者既有交叉、又有异同。https://www.runoob.com/w3cnote/charset-encoding.htmlhttps://blog.csdn.net/weixin_44198965/article/details/93125017。简单可以理解为字符集是人类理解的,编码格式是机器中的存储表示,当然有些实现比如mysql中说指定字符集其实是不正确的,实际应该是编码才是正确的叫法。然后不同的字符可以存储(没有超过给定编码格式的范围)或不可以存储(超过了给定编码格式的范围)到特定的编码中。

  就非西欧字符而言,比如中国以及港澳台,在任何编程语言的开发中都不得不考虑字符集及其表示。在c++中,对于超过1个字节的字符,有两种方式可以表示:

  1、多字节表示法;通常用于存储(空间效率考虑)。

  2、宽字符表示法,通常用于程序中(性能考虑)。

  目前最主要或最常见的编码应该来说包括:

  • ASCII,7位。
  • ISO-Latin-1(字符集)/ISO-8859-1(编码),8位。
  • UCS-2,16位定长。
  • UTF-8,8-32位变长。
  • UTF-16,16或32位变长。
  • UCS-4/UTF-32,32位定长。

  对于特定的字符,各编码格式所占的字节数和编码值如下:

  

说到UTF-16/UTF-32,不得不说BOM(byte order mark),它的作用跟网络编程中的字节码顺序概念一样,用于标识使用big endian或者little endian。

无BOM的字节流开始:

带BOM的字节流开始:

   在c/c++中,并没有原生支持GBK/GB18050/UTF-8的编码,如下:

  基本上广泛用的就是char和wchar_t(默认是UCS-2编码,而c默认是ascii解析,所以一定要设置正确的locale,如setlocale(LC_ALL,"chs"))。这两个也是c类型,c++ 11之后增加了对Unicode的支持,才支持char16_t和char32_t,见https://www.cnblogs.com/itdef/p/8022921.html

  对于常规控制台输入的,基本上网上很多demo了,所以接下去来看下从文件或者网络socket端过来的utf-8或者GBK编码如何处理的。

windows和linux下宽字符处理差异

// c++下常量字符串不能赋值给char指针
const wchar_t* cn_name;
const char* ext;
setlocale(LC_ALL, "chs"); // windows下必须使用chs,不能使用zh_CN.GBK,很多网上的示例是不正确的如https://wenku.baidu.com/view/40b0a0a672fe910ef12d2af90242a8956becaaac.htmlhttps://blog.csdn.net/BlackShadowT/article/details/104904752。 t.ext
= "ext name"; t.cn_name = L"中文扩展名balaba"; printf("ext=%s, cn_name=%ls\n",ext, cn_name); // ok 只有同时输出宽字符和标准字符才有意义,分开无意义 wprintf(L"cn_name=%s,ext=%s\n", cn_name, ext); // ext not ok

  所以除非特殊需求,日常情况下使用printf格式掩码ls即可满足日常需求。

  如果是跨平台编译,一定要确保原文件为UTF-8编码,不然windows下没有问题,到了linux下会报“error: converting to execution character set: Invalid or incomplete multibyte or wide character”,虽然加编译选项"-finput-charset=GBK"可以解决,但是并非上策。参见https://www.cnblogs.com/zhjh256/p/9288596.html

  在中文的输出显示上,受到显示终端如ssh/xshell使用何种编码解析收到的消息的影响,如下:

  

 

   

  SSH则没有选择编码格式的选项,默认中文版是GBK编码。所以如果一个终端或应用程序如notepad啥的同时显示GBK/UTF-8或其他多种编码,就会出现部分乱码、部分不乱码的情况。

  当前notepad++/010 Editor仅支持GB2312编码,vs code具有GBK扩展插件。

  https://gcc.gnu.org/onlinedocs/cpp/Character-sets.html

  https://blog.51cto.com/u_15127491/2655330 Unicode字符集与UTF-8\UTF-16\UTF-32编码格式的关系。

  https://www.cnblogs.com/kind064100611/archive/2013/12/23/3486771.html UTF-8编码和GBK编码解析差异。

  GBK 汉字内码扩展规范编码表(二)  http://ff.163.com/newflyff/gbk-list/

  汉字GBK编码与UTF-8编码对应关系 https://culat.gitee.io/chinesecharacterencodingtable/

posted @ 2017-01-26 09:13  zhjh256  阅读(493)  评论(0编辑  收藏  举报