今天由于在项目中用到一些与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. 第七章ssh sftp scp

    第七章ssh sftp scp 对数据进行了加密和压缩 版本号协商,可能客户端和服务端的版本号不一致,服务端向客户端发送一个ssh协商,告诉客户端使用的ssh协议的版本号是多少,客户端在接收到了这个协 ...

  2. iframe跨域通信window.postMessage()方法

    需求:A页面中要嵌入一个iframe,这个iframe是B页面,此时A页面需要得到B页面的一些信息. window.postMessage() 我们都知道浏览器的同源策略,即对于两个不同页面的脚本,只 ...

  3. pat乙级自我回顾:一般错误出现原因

    在obsidian里面写的有些引用没用,需要的可以评论区或者私信我呦~ 对于错误,末尾的换行不影响格式, 段错误: 一般是设置的数组小于题目给定的要求,循环条件i--写成i++,数组下标写错,也有可能 ...

  4. Vue2数据驱动渲染(render、update)

    上一篇文章我们介绍了 Vue2模版编译原理,这一章我们的目标是弄清楚模版 template和响应式数据是如何渲染成最终的DOM.数据更新驱动视图变化这部分后期会单独讲解 我们先看一下模版和响应式数据是 ...

  5. 使用Electron-builder将web项目封装客户端安装包 发布

    背景:之前用electron-packager将web项目打包成客户端时,exe文件只能在当前文件夹下运行,如果发送给别人使用 极不方便.所以我们可以用electron-builder将web项目封装 ...

  6. Let和Const区别,详细版本

    let:声明的是变量1.不存在变量提升 // var 的情况 console.log(foo); // 输出undefined var foo = 2; // let 的情况 console.log( ...

  7. pcm音频的录制、播放及转换

    操作系统 :Windows10_x64 pcm格式为原始音频数据,有时候会遇到需要录制.播放及转换的情况,这里记录下. 一.录制pcm音频 这里演示下使用Audacity进行pcm音频录音的过程. A ...

  8. MQ(消息队列)常见问题梳理

    MQ 中 broker 的作用,有无broker有什么差异? MQ(Message Queue)中的broker是消息队列的核心组件之一,它的作用是接收.存储.分发和传递消息.具体来说,broker主 ...

  9. 为什么我推荐你使用 systemd timer 替代 cronjob?

    概述 前几天在使用 Terraform + cloud-init 批量初始化我的实验室 Linux 机器.正好发现有一些定时场景需要使用到 cronjob, 进一步了解到 systemd timer ...

  10. 安装Minikube并启动一个Kubernetes环境

    安装Minikube并启动一个Kubernetes环境 Minikube 是一种轻量级的Kubernetes 实现,可在本地计算机上创建VM 并部署仅包含一个节点的简单集群.Minikube 可用于L ...