0
点赞
收藏
分享

微信扫一扫

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

  首先要来说一说字符集和编码的关系,这两者既有交叉、又有异同。​​https://www.runoob.com/w3cnote/charset-encoding.html​​

  就非西欧字符而言,比如中国以及港澳台,在任何编程语言的开发中都不得不考虑字符集及其表示。在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位定长。

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

  

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

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

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

无BOM的字节流开始:

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

带BOM的字节流开始:

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

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

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

  基本上广泛用的就是char和wchar_t(默认是UCS-2编码,而c默认是ascii解析,所以一定要设置正确的locale,如setlocale(LC_ALL,"chs"))。

  对于常规控制台输入的,基本上网上很多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.html、javascript:void(0)。
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"可以解决,但是并非上策。



举报

相关推荐

0 条评论