今天由于在项目中用到一些与C++混合开发的东西 ,需要通过socket与C++那边交换数据,没啥特别的,字节码而已,两边确定一种编码规则就行了。我们确定的UTF-8。关于C++的 这种又是宽字节 又是MessageBoxW 又是MessageBoxA 的 ,说实话相比C#而言 搞的确实非常的和稀泥 搞的非常的糊,别说新手 有些不是新手的都搞不明白。

字符串字面量怎么被编码成字节的

什么是字符串?C#里的 string?C++里的char* ? 字符串的本质是什么?字符串不过是一个特殊的数据字节包装 带有编码信息,特别是C++的 更原始 更便于我们想清楚这个底层,其实其他的已经迎刃而解了。首先我们无论如何确定一个东西  那就是交换的东西是字节码 ,说白了 也就是C++ 里的char [ ]  也就是char *,在我不管你编码的情况下 我新建VC++项目 在代码里这样写:

1 char str1[] = "中a";
2 printf("%s\r\n", str1);

能不能输出东西?能不能输出中文 当然能,那这个str1 字节码到底是什么字节码, 只要我们把这个搞明白就可以了。一切未知的恐惧源于不明白。我们先调试C++代码 取到字节码,然后编写下面这两句C#代码:

1 byte[] bts2 = new byte[] { 0xd6, 0xd0, 0x61 };
2 Console.WriteLine(Encoding.GetEncoding("gb2312").GetString(bts2));

正常输出了C++代码里的中文 由此可见C++里默认代码到字节  的字面量转换 就是gb2312 ,就这样而已。就这样而已 ,真的就这么点东西 ,事情不要歪呀歪的想想复杂了。你看C++里是char [ ] 还不像C#的string经过包装的 更便于你想明白这个过程。不是说C++有std库么 不是有string 么 还没讲呢 ,C++这门语言呢又好又不好 设计特点是暴露的细节多 各个细节你都可以自己控制 让会用的人知道自己在做什么 ,但是也有些坑,其实string 就是char[] 的变种而已。你看C++里 在你琢磨不透的情况下悄然在你不知情编码的情况下转换成了字节码,C#的string 封装的 不会给你这个机会 有明确的Encoding库调用指定编码。

窄字符和宽字符 ,怎么个宽法

C++里字符串的字面量分为两种 一种是普通的窄字符 ,也就是普通的char [ ] 一个元素占1字节, 另一种是宽字符 wchar_t [ ] 一个元素占2字节,_T("中a") 或者L"中a" 这种就是强行表示Unicode宽字符字面量。 宽字符 怎么个宽法呢,我们说他是Unicode 也就是utf-16,我们用C#进行验证:

1 byte[] bts3 = new byte[] {  0x2d,0x4e, 0x61,0x00, };
2 Console.WriteLine(Encoding.Unicode.GetString(bts3));

好了,这就明朗了,C++这玩意儿 由于历史遗留原因,直接在代码书写字符串字面量搞了两套标准 窄字符和宽字符 ,你看上面的同字符里面的字节码整的两套标准  这就很扯,整的被迫大多数C++的函数 或者接口都要按照这个套路玩。就有了看到的MessageBoxA ()接受char[]窄字符参数,MessageBoxW()接受宽字符参数 ,不要有误区哈 觉得char[ ] 就不能输出中文 ,能不能是由对应的地方能不能解析这个字节码决定的 而不是其他。

关于UTF-8

utf-8的现实意义更大于编程的字面量意义 ,为什么这么说,现在网络 数据交换都是UTF-8 编码,C++编程 字面量 没有所谓UTF-8这个说法 ,UTF-8是一种落地编码,落地编码 懂吗?就像图像编程  保存最终格式有.jpg .png,utf-8 他是变长的 对于字符串处理会出现很多问题 不利于程序处理,图像编程中不管你jpg png格式也好载入到内存中最后都是易于处理的BMP内存映像。编程中都是Unicode因为2字节代表一个字符 标标准准的 是对齐的,利于编程处理。还有 utf-8 一个中文3字节 其实比utf-16 一个中文2字节 多, 但是如果是英文的话 就是1字节 可以实现Unicode到ASCII的无缝转换 可以处理一些老旧系统的兼容问题。 C++里Unicode可以通过手段转换为UTF-8:

1 void UnicodeToUtf8(const wchar_t* unicode,char  utf82[],int * lenout)
2 {
3 int len;
4 len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
5 char szUtf82[50] = { 0 };
6 *lenout = len;
7 WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf82, len, NULL, NULL);
8
9 }

关于VC++项目属性里的设置字符集

什么意思呢:

当选择“使用Unicode字符集”时,编译器会增加宏定义——UNICODE;而选择“使用多字节字符集”时,编译器则不会增加宏定义——UNICODE。https://blog.csdn.net/huashuolin001/article/details/95620424
当选用“使用Unicode字符集”时,调用函数MessageBox,实际使用的是MessageBoxW,MessageBoxW关于字符串的入参类型是LPCWSTR,使用MessageBox时,字符串前需加L::MessageBox(NULL, L"这是一个测试程序!", L"Title", MB_OK);

基于gb2312和Unicode编码我就不细说了哈,如果你想你的程序能够卖到国外在世界范围内使用,那么请使用Unicode。

最后 ,一些测试的大杂烩代码:

  1 // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include <iostream>
6 #include "h1.h"
7 #include "FqTabData.h"
8 #include "test1.h"
9
10 #include <windows.h>
11 #include <string>
12 #include <iomanip>
13 #include <type_traits>
14
15 using namespace std;
16
17
18 //引用的使用方式
19 void test1(int &r){
20 r = r+1;
21 }
22
23 void UnicodeToUtf8(const wchar_t* unicode,char utf82[],int * lenout)
24 {
25 int len;
26 len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
27 char szUtf82[50] = { 0 };
28 *lenout = len;
29 WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf82, len, NULL, NULL);
30
31 }
32 int _tmain(int argc, _TCHAR* argv[])
33 {
34
35 setlocale(LC_ALL, "");//注意控制台输出要先加上这句哈要不然无法输出中文
36 wchar_t wstr2[] = L"中a";
37 wprintf(L"%ls\r\n", wstr2);
38
39 char str1[] = "中ab";
40 printf("%s\r\n", str1);
41 return 0;
42 //关于c++里的编码问题
43 // 并非 不在在项目属性里设置编码字符集 为Unicode 就不能显示中文
44 //char str11[] = "中a"; printf("%s", str11);
45 //这段代码照样显示中文,中a被编译器编成3个元素存在str11 里+\0结尾
46 //当选择“使用Unicode字符集”时,编译器会增加宏定义——UNICODE;而选择“使用多字节字符集”时,编译器则不会增加宏定义——UNICODE。
47 //https://blog.csdn.net/huashuolin001/article/details/95620424
48 //当选用“使用Unicode字符集”时,调用函数MessageBox,实际使用的是MessageBoxW,MessageBoxW关于字符串的入参类型是LPCWSTR,
49 //使用MessageBox时,字符串前需加L
50 //::MessageBox(NULL, L"这是一个测试程序!", L"Title", MB_OK);
51
52 //关于这个L ,等同于_T("") Tchar 这些玩意儿他们都有同等意义
53 //可以傻瓜的理解 L 本身就是搞一个宽字符型 字符串 ,每个字符占2字节
54 //wchar_t ws[] = L"国家";
55 //设置为Unicode 就意味着宽字符 就意味着字符串 要加L
56 //就像前面的 好多函数接口有两种版本 MessageBoxA MessageBoxW ,
57 //MessageBoxW就意味着你要传一个宽字符数组进去 也就是 wchar_t 或者L"dd"
58
59 //注意多字节字符集是一个很容易让人费解的玩意儿,
60 //我们说 utf-8是 一种Unicode的落地编码
61 //编程里都是用 Unicode 不管项目设没设置Unicode字符集 wchar_t ws[] = L"国家"; 得到的都是宽字符串
62 //但是编程代码里 没有utf-8 这一说法 utf-8是变长的 也就是多字节 他是一种编码落地
63 //你想想你整个变长 别人接口怎么写 ,怎么达到在让你用变长省内存的同时 识别你的有效字符
64 //如果数组里存utf-8 你想想 别人要以字节数读字符 半个的时候怎么搞
65 //这跟gdi图像处理是同一个道理 jpg png 各种是落地格式都可以读进来 但是到内存都是bmp
66
67 //还有不论哪种printf 或者其他接口 都不支持所谓的utf-8的参数 也没这种接口可言
68 //https://zhuanlan.zhihu.com/p/23190549
69 //前几天在微博上受到了@Belleve给我的启发,于是简单地实现了几个在 Windows
70 //下接受 UTF - 8 参数的 printf 系列函数。大致思路是判断当前 stdout / stderr
71 //是否为控制台,如果是控制台则将参数转为 UTF - 16 后调用 wprintf 输出,否则不转换直接调用 printf。
72
73 //L 是一个很微妙的 ,称之为转换为宽字符的字面量 什么叫字面量 根据你当前编程环境 以及源代码编码 转换成对应的字节
74 //L"发" 字面量 你细品
75 setlocale(LC_ALL, "");
76
77
78
79
80 printf("--------------------");
81 //wchar_t wc = L'破';
82 std::wstring wstr = L"破a的";
83 std::cout << wstr.size() << std::endl;
84 //utf-8 只是流行 ,事实上utf-8 一个汉字要占3字节 而utf-16一个汉字一字节
85 /*wchar_t wstr2[] = L"破晓S";
86 wprintf(L"%ls", wstr2);*/
87 printf("--------------------//");
88
89 char utf82[50] = { 0 };
90 int len = 0;
91 UnicodeToUtf8(wstr2, utf82, &len);
92 //char* str222 = UnicodeToUtf8(wstr2);
93 //printf("%S", str222);
94 //printf("aaa");
95 return 0;
96 //
97 //c++ 中指针的变种 引用的使用方式
98 printf("aaa\r\n");
99
100 int a = 123;
101 int& b = a;
102 a = 456;
103 printf("%d \r\n", b);
104
105 test1(b);
106 printf("%d \r\n", b);
107
108 int c = 345;
109 test1(c);
110 printf("%d \r\n", c);
111 return 0;
112 }

C++中的字符串编码处理的更多相关文章

  1. Mapreduce中的字符串编码

    Mapreduce中的字符串编码 $$$ Shuffle的执行过程,需要经过多次比较排序.如果对每一个数据的比较都需要先反序列化,对性能影响极大. RawComparator的作用就不言而喻,能够直接 ...

  2. 使用自己的Python函数处理Protobuf中的字符串编码

    我目前所在的项目是一个老项目,里面的字符串编码有点乱,数据库中有些是GB2312,有些是UTF8:代码中有些是GBK,有些是UTF8,代码中转来转去,经常是不太清楚当前这个字符串是什么编码,由于是老项 ...

  3. 关于python中的字符串编码理解

    python2.x 中中间编码为unicode,一个字符串需要decode为unicode,再encode为其它编码格式(gbk.utf8等) 以gbk转utf8为例: s = "我是字符串 ...

  4. javascript中的字符串编码、字符串方法详解

    js中的字符串是一种类数组,采用UTF-16编码的Unicode字符集,意味字符串的每个字符可用下标方式获取,而每个字符串在内存中都是一个16位值组成的序列.js对字符串的各项操作均是在对16位值进行 ...

  5. Python2和Python3中的字符串编码问题解决

    Python2和Python3在字符串编码上是有明显的区别. 在Python2中,字符串无法完全地支持国际字符集和Unicode编码.为了解决这种限制,Python2对Unicode数据使用了单独的字 ...

  6. python中的字符串编码问题——1.理解编码和解码问题

    理解编码与解码(python2.7):1)编码 是根据一个想要的编码名称,把一个字符串翻译为其原始字节形式.>>> u_str=u'字符串编码aabbbcccddd'>> ...

  7. JavaScript中有对字符串编码的三个函数:escape,encodeURI,encodeURIComponent

    JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...

  8. Python3中转换字符串编码

    在使用subprocess调用Windows命令时,遇到了字符串不显示中文的问题,源码如下:#-*-coding:utf-8-*-__author__ = '$USER' #-*-coding:utf ...

  9. Code::Blocks开发中的字符串编码错误

    刚开始使用Code::Blocks开发Windows中文应用程序的朋友们,如果在代码中使用了中文字符串,编译时可能遇到过Illegal byte sequence或Failure to convert ...

  10. python中的字符串编码问题——4.unicode编解码(以实际工作中遇到的韩文编码为例)

    韩文unicode编解码  问题是这样,工作中遇到有韩文数据出现乱码,说是unicode码. 类似这样: id name 323 52186863 149 63637538 314 65516863 ...

随机推荐

  1. HAL层分析

    1. 安卓HAL模块基本 2. 定义hal层代码的5个特性 1)硬件抽象层具有与硬件的密切相关性. 2) 硬件抽象层具有与操作系统无关性. 3) 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功 ...

  2. 谈谈Selenium中的日志

    谈谈Selenium中的日志 来源于一位同学,"老师为啥firefox执行后会有日志文件,chrome没有呢?" 比对 你打开chrome浏览器 from selenium imp ...

  3. 深入理解 Python 虚拟机:字节(bytes)的实现原理及源码剖析

    深入理解 Python 虚拟机:字节(bytes)的实现原理及源码剖析 在本篇文章当中主要给大家介绍在 cpython 内部,bytes 的实现原理.内存布局以及与 bytes 相关的一个比较重要的优 ...

  4. 一遍博客带你上手Servlet

    概念 Servlet其实就是Java提供的一门动态web资源开发技术.本质就是一个接口. 快速入门 创建web项目,导入servlet依赖坐标(注意依赖范围scope,是provided,只在编译和测 ...

  5. MQTT(EMQX) - Java 调用 MQTT Demo 代码

    POM <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse ...

  6. 案例: 利用 Hugging Face 进行复杂文本分类

    Witty 与 Hugging Face 专家加速计划的成功案例 如果你对如何更快构建 ML 解决方案感兴趣,请访问 专家加速计划 登陆页面并通过 填写表单 联系我们! 业务背景 随着 IT 技术不断 ...

  7. VBA GET POST HTTP VBA网络爬虫 最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码

    最新Excel自动获取股票信息源码 EXCEL自动获取网络数据 最新VBA自动抓取股票数据源码 通过接口获取股票数据内容的主要优点包括以下几点: 实时性高:通过访问股票数据接口,可以实时获取到股票的实 ...

  8. [Linux]Linux发展历程

    古人云,知其然知其所以然.马哲思想指导着我们,任何事物.问题,离不开:为什么(Why,事物从哪里来?).是什么(What,事物的定位?).怎么做(How,到哪里去?)的哲学3问. 继上个月算是相对彻底 ...

  9. [数据库/Linux]CentOS7安装MySQL Percona版(RPM方式)

    OS: CentOS7 (x86_64) MySQL: MySQL Percona 5.7.31-34 0 前置条件 已配置完成YUM源 已卸载先前可能安装的MySQL rpm -qa | grep ...

  10. 清理过时的.NET SDK 和 运行时

    TL;DR .NET 卸载工具 随着这几年.NET 的快速发展,电脑上的.NET SDK 和 runtime 也在不断的积累.每个sdk动辄都是上百兆的空间占用,很快本来就不富裕的C盘空间就更加紧俏了 ...