今天由于在项目中用到一些与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. HGD1-LSP-函数集-网络整理

    CAD LSP函数集 header

  2. win10_pyhive链接hive失败,提示:Could not start SASL

    win10_pyhive链接hive失败,提示:Could not start SASL https://blog.csdn.net/weixin_45684985/article/details/1 ...

  3. 2022中职组网络空间安全 A模块

    A-1任务一 登录安全加固 1.密码策略(Windows,Linux) 主要是针对windows和Linux的系统加固,类似于运维的题目 a.设置最短密码长度为15: 这里并没有说明具体是Window ...

  4. Leftpad事件 我们是不是早已忘记该如何好好地编程?

    多年前的Leftpad 撤包事件使得React . Babel 和许多流行的npm模块都受到波及,无法正常运行. 这些受到影响的模块都引入了一个叫做 left-pad 的模块. 以下就是这十一行代码: ...

  5. Skywalking搭建

    因毕设前端太丑,所以后端要稍微搞的高大上一点才能忽悠住老师,所以分享一下搭建skywalking的步. 我是参考https://baijiahao.baidu.com/s?id=17211835411 ...

  6. Maven 自动化构建

    一.Maven:是一款服务于 Java平台的自动化构建工具 [1]Maven可以将一个项目按模块划分成不同的工程,利于分工协作;[2]Maven可以将 jar包保存在自己的中央"仓库&quo ...

  7. 网络----OSI七层

    OSI 订制的是一个用于计算机或通信系统间互联的标准体质(一般称为OSI参考模型或七层模型) OSI 模型把网络通信的工作分为7层分别是: 常用内容:物理层 数据链层 网络层 注解 OSI 7层 1. ...

  8. 温故知新----线程之Runnable与Callable接口的本质区别

    温故知新----线程之Runnable与Callable接口的本质区别 预备知识:Java中的线程对象是Thread,新建线程也只有通过创建Thread对象的实例来创建. 先说结论 1 Runnabl ...

  9. QML和QT

    推荐一些学习qml教程 Qt官方的QML教程: https://doc.qt.io/qt-5/qtqml-index.html,这是一个由Qt官方提供的完整的QML教程,包含了所有基本知识和高级语法. ...

  10. 单元测试、文档测试、读写文件、StringIO和BytesIO

    1.单元测试就是为了测试程序执行的正确性 2.编写单元测试时,需要编写一个单元测试类,继承unittest TestCase类 3.单元测试最常用的断言是assert,断言期望抛出指定的异常 4.运行 ...