C++中的字符串编码处理
今天由于在项目中用到一些与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++中的字符串编码处理的更多相关文章
- Mapreduce中的字符串编码
Mapreduce中的字符串编码 $$$ Shuffle的执行过程,需要经过多次比较排序.如果对每一个数据的比较都需要先反序列化,对性能影响极大. RawComparator的作用就不言而喻,能够直接 ...
- 使用自己的Python函数处理Protobuf中的字符串编码
我目前所在的项目是一个老项目,里面的字符串编码有点乱,数据库中有些是GB2312,有些是UTF8:代码中有些是GBK,有些是UTF8,代码中转来转去,经常是不太清楚当前这个字符串是什么编码,由于是老项 ...
- 关于python中的字符串编码理解
python2.x 中中间编码为unicode,一个字符串需要decode为unicode,再encode为其它编码格式(gbk.utf8等) 以gbk转utf8为例: s = "我是字符串 ...
- javascript中的字符串编码、字符串方法详解
js中的字符串是一种类数组,采用UTF-16编码的Unicode字符集,意味字符串的每个字符可用下标方式获取,而每个字符串在内存中都是一个16位值组成的序列.js对字符串的各项操作均是在对16位值进行 ...
- Python2和Python3中的字符串编码问题解决
Python2和Python3在字符串编码上是有明显的区别. 在Python2中,字符串无法完全地支持国际字符集和Unicode编码.为了解决这种限制,Python2对Unicode数据使用了单独的字 ...
- python中的字符串编码问题——1.理解编码和解码问题
理解编码与解码(python2.7):1)编码 是根据一个想要的编码名称,把一个字符串翻译为其原始字节形式.>>> u_str=u'字符串编码aabbbcccddd'>> ...
- JavaScript中有对字符串编码的三个函数:escape,encodeURI,encodeURIComponent
JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...
- Python3中转换字符串编码
在使用subprocess调用Windows命令时,遇到了字符串不显示中文的问题,源码如下:#-*-coding:utf-8-*-__author__ = '$USER' #-*-coding:utf ...
- Code::Blocks开发中的字符串编码错误
刚开始使用Code::Blocks开发Windows中文应用程序的朋友们,如果在代码中使用了中文字符串,编译时可能遇到过Illegal byte sequence或Failure to convert ...
- python中的字符串编码问题——4.unicode编解码(以实际工作中遇到的韩文编码为例)
韩文unicode编解码 问题是这样,工作中遇到有韩文数据出现乱码,说是unicode码. 类似这样: id name 323 52186863 149 63637538 314 65516863 ...
随机推荐
- 如何利用Apifox通过签名计算及数据加解密进行用户认证接口测试?
用户注册场景:输入签名数据signature,appId,13位时间戳timestamp,6位随机数nonce,merchantId(非必填,本次不填)的请求参数发送给服务器,服务器返回响应数值后,校 ...
- keras图片数字识别入门AI机器学习
通过使用mnist(AI界的helloworld)手写数字模型训练集,了解下AI工作的基本流程. 本例子,要基于mnist数据集(该数据集包含了[0-9]的模型训练数据集和测试数据集)来完成一个手写数 ...
- odoo 权限管理学习总结
环境 odoo-14.0.post20221212.tar base_user_role-12.0.2.1.2.zip 下载地址: https://apps.odoo.com/apps/modules ...
- K8S部署应用详解
# 前言 首先以SpringBoot应用为例介绍一下k8s的发布步骤. 1.从代码仓库下载代码,比如GitLab:2.接着是进行打包,比如使用Maven:3.编写Dockerfile文件,把步骤2产生 ...
- 在echaerts中渲染50万条数据的优化方案
背景:项目需求中要在页面上渲染大约50万条左右的波形数据图表 那么如何解决渲染中的卡顿呢? 肯定是要从服务端和前端一起优化这是毋庸置疑的. 1.服务端: 服务端耗时最多的一定是在数据库的筛选数据的行为 ...
- Linux下学习FPGA
声明(叠甲):鄙人水平有限,本文章仅供参考. 1.环境 推荐使用 Ubuntu20.04这是我使用多个版本中最好用的一个,相关安装教程可以自行上网搜索这不再赘述,但要补充的一点的是源推荐使用中科大的源 ...
- 百度360搜索关键词提交.py(亲测有效)
import requests keyword = "Python" try: kv = {'wd':keyword} # 百度 kv1 = {'q':keyword} # 360 ...
- RFM客户分类模型的应用——R语言
RFM模型是衡量客户价值和客户创造利益能力的重要工具和手段.在众多的客户关系管理(CRM)的分析模式中,RFM模型是被广泛提到的.该机械模型通过一个客户的近期购买行为.购买的总体频率以及花了多少钱3项 ...
- [Linux]监控外部用户登录及外部主机连接情况
1 外部用户/外部主机 /var/log 在CentOS系统上,用户登录历史存储在以下这些文件中: /var/log/wtmp 用于存储系统连接历史记录被last工具用来记录最后登录的用户的列表 /v ...
- 和我一起学 Three.js【初级篇】:1. 搭建 3D 场景
欢迎关注「前端乱步」公众号,我会在此分享 Web 开发技术,前沿科技与互联网资讯. 0. 系列文章合集 本系列第 6,7 章节支持微信公众号内付费观看,将在全系列文章点赞数+评论数 >= 500 ...