C++中的字符串编码处理

这篇具有很好参考价值的文章主要介绍了C++中的字符串编码处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

首先源码文件只不过是一个文本文件,你编辑器里打字输入中文 然后用编辑器打开能正常显示中文,那么在硬盘上源码文本肯定是以中文编码进行存储 编辑器也是以对应中文编码进行解析的 比如gb2312 比如Unicode 这个就不细说了。什么是字符串?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 ,就这样而已。就这样而已 ,真的就这么点东西 ,不要探究是什么机制驱使VC++默认把字符串转换到了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++中的字符串编码处理

 好了,这就明朗了,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++项目属性里的设置字符集

什么意思呢:

C++中的字符串编码处理

 当选择“使用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);

多字节,默认的窄字符char[]带中文 就是典型的多字节,接上面章节说明 多字节+中文 对于字符串处理分割 会带来很多问题,所以带中文请尽量使用宽字符。然后另一个 基于gb2312和Unicode编码我就不细说了哈,如果你想你的程序能够卖到国外在世界范围内使用,那么请使用Unicode,也就是 L" " 宽字符。C++里这些概念搞的比较糊 ,我描述的这些也是个意会 ,也许某些细节部分说错了 像原来文章里那些评论里那样 尖锐的指出来  不怕批评。

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

  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 }

 文章来源地址https://www.toymoban.com/news/detail-444514.html

到了这里,关于C++中的字符串编码处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】String在OJ中的使用(一):仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加

    前言: 🎯个人博客:Dream_Chaser 🎈博客专栏:C++ 📚本篇内容:仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加 目录 917.仅仅反转字母  题目描述: 387.字符串中的第一个唯一字符 题目描述: HJ1 字符串最后一个单词的长度

    2024年04月09日
    浏览(108)
  • c++:string相关的oj题(把字符串转换成整数、344.反转字符串、387. 字符串中的第一个唯一字符、917. 仅仅反转字母)

    传送门 首先处理空字符串为空的情况() 再处理第一个字符可能为 + - 的情况,直接定一个 flag 初始化为1,遇到 - 就赋值为-1 接下来就利用迭代器进行循环,如果是字符数字就直接使用 ret = ret * 10 + (*it - \\\'0\\\'); 是其他字符,直接return 0;了 传送门 大家学习了c++,可能直接就想

    2024年01月23日
    浏览(79)
  • 【自然语言处理】NLP入门(一):1、正则表达式与Python中的实现(1):字符串构造、字符串截取

       语言 是一种使用具有共同处理规则的沟通指令的广义概念,这些指令可以通过视觉、声音或触觉等方式传递。语言可以分为自然语言、动物语言和计算机语言。    自然语言 是人类发展过程中形成的一种信息交流方式,它包括口语和书面语,并且反映了人类的思想。

    2024年03月12日
    浏览(146)
  • c++:string相关的oj题(415. 字符串相加、125. 验证回文串、541. 反转字符串 II、557. 反转字符串中的单词 III)

    传送门 首先,定义两个指针 index1 和 index2 分别指向两个输入字符串的最后一位,用来从后往前遍历字符串。 然后定义一个变量 next 用来表示进位,初始化为 0。 接下来使用一个循环来遍历两个字符串,直到 index1 和 index2 都小于 0。在循环中,每次取出 index1 和 index2 对应位置

    2024年01月23日
    浏览(59)
  • 《剑指 Offer》专项突破版 - 面试题 15 : 字符串中的所有变位词(C++ 实现)

    题目链接 :LCR 015. 找到字符串中所有字母异位词 - 力扣(LeetCode) 题目 : 输入字符串 s1 和 s2,如何找出字符串 s2 的所有变位词在字符串 s1 中的起始下标?假设两个字符串中只包含英文小写字母。例如,字符串 s1 为 \\\"cbadabacg\\\",字符串 s2 为 \\\"abc\\\",字符串 s2 的两个变位词 \\\"c

    2024年01月18日
    浏览(76)
  • Python字符串的编码和解码

    不同计算机之间进行数据传输,实际上传输的是二进制数据。 将str类型转换成bytes类型,需要用到字符串的encode()方法 Str.encode(encoding=’utf-8’,                Errors=’strict/ignore/replace’) 将bytes类型转换成str类型,需要用到bytes类型的decode()方法 Bytes.decode(encodin

    2024年01月22日
    浏览(50)
  • android/ios 一键抽取硬编码字符串

    由于老项目 做国际化困难,抽取繁琐 最终实在蛋疼 最终开发插件来解决 android studio 插件 一键抽取硬编码字符串 xcode 一键抽取硬编码字符串 环境配置android studio ,appcode idea 环境类似 1.安装插件 插件下载点击 安装教程查看地址(可以之后忘记博客地址 可以在插件描述的地方找

    2024年02月07日
    浏览(43)
  • IDE /字符串 /字符编码与文本文件(如cpp源代码文件)

    前期在整理 《IDE/VS项目属性中的 <字符集> 配置项》 和 《IDE /Qt Creator 文本编辑器之文件编码设置》和 《IDE /C4819: 该文件包含不能在当前代码页(936)中表示的字符》等文章的过程中,做了不少关于字符编码的测试,解决了一些问题,但是也让我有了些新的问题和思考。简单

    2024年02月16日
    浏览(35)
  • [译]JavaScript中Base64编码字符串的细节

    本文作者为 360 奇舞团前端开发工程师 本文为翻译 原文标题:The nuances of base64 encoding strings in JavaScript 原文作者:Matt Joseph 原文链接:https://web.dev/articles/base64-encoding   Base64编码和解码是一种常见的将二进制内容转换为适合Web的文本的形式。它通常用于data URLs,比如内嵌图片

    2024年02月05日
    浏览(52)
  • 编码技巧 --- 如何实现字符串运算表达式的计算

    最近做一个配置的功能,需求是该配置项跟另一个整形配置项关联,具有一定的函数关系,例如有一个配置项是值为 N ,则另一配置 F 项满足函数关系 (F=2/(N+1)) 。这个函数关系是客户手动输入,只需要简单的四则运算,所以我们要做的就是判断四则运算表达式是否有效,且

    2024年02月13日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包