中文字符占用字节即相关原理(实现中文(中英混合)字符串的反转)

如有不对欢迎指正。 

目录

 一.ASCLL字符和中文字符

1.使用无符号数表示的原因(对于中文字符): 

2.但是并不是所有情况都是用无符号数(以下目前只是猜测,如有问题欢迎指正) :

1. 什么时候使用无符号数表示:     

2. 不需要使用的情况: 

3.我们上面说到的char是有符号类型,可我们平时使用可以直接表示字符呀? 

 二.对于中文字符,将一个字符串的中文字符传给另一个

三.实现中文字符串的反转 

方法一 :  

方法二:   


 一.ASCLL字符和中文字符

char类型

char类型我们在写代码的时候经常会使用,它用于存储定义一个存储字符的变量,但是我们定义char类型一般是用来存放一些英文字符等,这些字符都有一个特点:都是ASCLL中指定的字符。 

说是字符其实存储的是一些二进制数,我们知道一个字节有八位,一位可以存储0,1两个二进制位,所以八位一共可以表示2^8 = 256 个数据,但是,对于ASCLL码我们使用的一般是128个,所以只需要低7位即可存储下。最高位存0即可。(后面新增的(128-255)有些编码可能不兼容)

所以,char定义的变量只能用来存放ASCLL码表中的字符,所以char类型的变量只占一个字节。(因为一个字节就足够表示全部ASCLL码的值,不需要再多占用内存了)。 

那么怎么能让这128个数据和字符对照起来呢,其实就是一个查表的过程(可以看下ASCLL码表) 。

但是,由于历史原因,ASCLL码表中是没有中文字符的, (所以我们无法使用char类型的变量来表示一个中文字符)。为了能够使用中文字符,衍生出了GBK,GB2312等编码字符集,这些字符集兼容ASCLL码字符(只兼容前127个,后新增的不兼容)。

1.使用无符号数表示的原因(对于中文字符): 

因为ASCLL码字符已经基本占用了一个字节的内存来表示相应的字符,再加上中华文化博大精深,一个字节(最多才256个数据)怎么能放的下我们的汉字呢,所以中文字符使用两个字节来保存(大部分) ,而且为了能够确定你输出的是中文字符,相应编码做出了不同的规定。其中一个是:两个字节的高第一个字节必须为1(这也就说明了,存放这些数据需要一个无符号类型(因为有符号最高位是表示正负的,会出问题)--后面会说到)。GBK和GB2312都是如此。(当然其它不同编码可能会有不同--但是依然使用无符号数进行表示数据)。

2.但是并不是所有情况都是用无符号数(以下目前只是猜测,如有问题欢迎指正)

1. 什么时候使用无符号数表示:     

当我们需要使用字符对应的二进制数据进行数学运算和比较的时候,我们使用无符号数据最好。

2. 不需要使用的情况: 

当我们只是想通过二进制输出对应的字符时(平时定义字符,输出都属于这一类型)。我们可以不需要考虑有无符号。 

其实大部分情况下都不需要使用,我们平时也遇到很多,例如: 我们使用一个char a[] = "我爱你",对于这个字符串,就是一个包含7个字节的字符串,每个字节是一个char类型的空间,如果如上述(使用无符号数的原因)我们表示这个字符串,应该使用无符号类型才行,但是使用过的都知道,我们直接去输出这个字符串也是没有问题的。(也就是说,我们使用char这样的符号类型,它也能正确的查表)。

举一个例子,char类型字符的取值范围是 -128  ---  127 ,当我们赋值超过127其就是一个负数了,那么按照上述所说(使用无符号数表示),应该是无法正确表示出字符的。但是经过测试之后发现是没有问题的,(但是由于我们默认使用的代码页(一般为936),是不包括新增的128-255位ASCLL码,所以输出需要修改代码页(看代码)), 


int main(void)
{SetConsoleOutputCP(437);char a = 254;printf("%c", a);system("pause");return 0;
}

上述代码,进行了代码页的转换,否则无法输出128-255位的ASCLL码数(因为是新增的不兼容),我们看代码 -- 使用char类型,赋值为254,但由于前面char类型的范围,这个值是溢出的,所以实际它的值为:-2, 原码: 1000 0010, 补码: 1111 1110, 我们如果将其补码看作无符号数转换成数字,为254。

当我们以字符形式输出时,会发现可以正常输出,而且正好是ASCLL码第254号位置的字符。 

 就是本图的正方形。

结论:  所以,1)我们数据在计算机中以补码形式存储,那么计算机在查表时(表中为无符号数),不会区分正负,(如果只是根据二进制输出相应字符,不需要考虑符号)只是看该数据与表中哪个数据对应,然后输出对应的字符。

2)只有在我们使用字符对应的二进制数据计算,比较,以有符号数输出时才会有明确的正负。建议使用无符号类型。(这些都是自己的猜测,如果不对请指正)。  

所以,这也说明了,如果一个中文字符对应的二进制数据,最高位都为1的话(有符号类型应该是个负数),我们使用char类型输出字符串时却没有问题。 

3.对于使用使用无符号数表示字符对应的数据(就是二进制组成的数字),可能会有疑问。 

3.我们上面说到的char是有符号类型,可我们平时使用可以直接表示字符呀? 

原因 :  上面说到过,ASCLL一般使用低七位即可,最高位一般为0.

 如图。 作为无符号数,最高位为0的时候为正数,它和其对应的无符号数表示的值是一样的(如果为1就不一样了,多一个负号吗),所以我们平时使用char也是可以的。

 二.对于中文字符,将一个字符串的中文字符传给另一个

对于字符串, 定义:  char  s[] = "我爱你";   char s2[100] = {0}(定义了一个占用100字节的数组); 我们要将s指向的字符串拷贝到s2中。

1.2.首先, 我们上面说到一个中文字符占用两个字节,一个char占用一个字节,

 

如上图,一个框子为一个字节(最后\0表示字符串的结束) ,所以对于字符数组,s它存储的字符串虽然只有三个元素,但是它却占七个字节(还有一个字符串结束符)。

从这可以更加直观的看出,为什么不能使用char来打印中文字符了,人家占用两个位置,你只给一个位置,不出问题才怪。 

2.想要将s中的字符串拷贝到s2中,与直接拷贝ASCLL字符不一样,但是也差不多。 

一个汉字占用两个字节,我们只需要将这两个字节按照顺序拷贝到s2中即可。例: s2[0] = s1[0],

s2[1] = s1[1] -- 后面的中文一起类推,最后加一个字符串结束符就可以了。(原因:其实一个汉字,对应的是这两个字节所组成的0,1数字组合,然后对应查表就可得到,此处,我们按照顺序,将这些数字组合拷贝到目标数组--它们的顺序是没有改变的所以对应的还是哪个汉字,所以实现了拷贝) 

对于字符串的输出,编译器使用相应的编码,所以可以输出中文等。 

三.实现中文字符串的反转 

方法一 :  

#include <iostream>
#include <Windows.h>
#include <string>
#include <errno.h>
#include <string.h>using namespace std;#define STRTEMPLEN 30char* exchangeChineseStr(const char* str);/*字符串常量的值为首字符的地址,使用指针+一个字符占用字节数,可以跳过相应字节输出后面字符串,中文字符一个占用两个
字节,所以+2*/int main(void)
{string str;char* result = NULL;cout << "请输入一个字符串" << endl;cin >> str;// 错误检测if (cin.fail()){cerr << "输入失败,原因:" << strerror(errno) << endl;exit(1);}if ((result = exchangeChineseStr(str.c_str())) != NULL){printf("%s\n", result);  //输出乱码的原因: 是因为返回了局部变量}system("pause");return 0;
}char* exchangeChineseStr(const char* str)
{if (str == NULL){cout << "传入字符串为空" << endl;return NULL;}int len = strlen(str);  // 计算长度//printf("%d", len); char strTemp[STRTEMPLEN] = { 0 };strcat(strTemp, str);  // 得到字符串的字节数char strReturn[STRTEMPLEN] = { 0 };//printf("%s\n",strReturn);for (int i = len; i > 0; i -= 2)  // 中文字符占两个字节,所以一次加2才能找到下一个字符,否则会出现乱码。{//printf("%s", strTemp);   //printf("%s", strTemp + 4);     strcat(strReturn, (strTemp + (i-2)));  *(strTemp + (i-2)) = '\0';  // 一个汉字占用两个字节,将这两个字节都设置为0*(strTemp + (i-1)) = '\0';}char* a = strReturn;printf("%s\n", a);return strReturn;
}

上面的代码,利用了中文字符串占两个字节的特性,从源字符串的尾部,以字符串的形式拼接到目的字符串的尾部,拼接之后将此位置设置成\0,然后再拼接下一位,直至结束。 (如图)

方法二:   

 此方法可以实现中文和英文混合反转。

#include <iostream>
#include <Windows.h>
#include <string>using namespace std;/*实现中英文混合转换-- 由于中英文占用字节数不同,所以需要判断相应字符是英文还是中文*/
void reserve(unsigned char* str); /*对字符串进行反向*/int main(void)
{unsigned char a[] = "我爱你";reserve(a);system("pause");return 0;
}void reserve(unsigned char* str)
{int len = strlen((char *)str); // 计算传入字符串的字节数unsigned char temp[1024]; // 创建一个1024字节的数组,用来临时存放转换后的数组// 定义两个指针,分别对str和temp进行操作unsigned char* p1 = str;  // p1指向str的开头unsigned char* p2 = temp + len; /*因为temp数组很大,但其实我们只需要它能够存放str所占字节数+1就行(因为还有一个结束符),此时p2存放数 据的结尾是,temp+len(首元素+len,就是最后一个位置--存放'\0')*/*p2-- = '\0'; // 做后一位为'\0'while (*p1){if (*p1 < 0x80)   // *p1中的数小于127,说明是英文字符{*p2-- = *p1++;}else  // 否则是中文字符{*(p2 - 1) = *(p1++);*p2 = *(p1++);p2 -= 2;}}printf("%s", temp);
}

1. 我们要实现中英文混合转换,因为:中文和英文所占用的字节不同,所以转换的方式也有差距,所以,要分情况。 

首先, 我们前面我们说到,汉字的高位都是1,英文为ASCLL码高位为0,如果为无符号,那么汉字的每一个字节都应该大于127(0x80),-- 此处需要与数据进行比较,所以所有字符都定义成无符号类型(不使用无符号会出错,(不使用无符号,那就是有符号,在比较时,汉字对应数据都是负值,都比127小,就都以ASCLL字符算了肯定出错))所以,每一个字节,比127大的都是汉字字符,相反为英文字符,然后按照顺序将字符串拷贝到目标字符串即可。

注意: 因为是逆转,所以要从后向前拷贝,但是中文字符一定要注意,每个字符的每个字节顺序不能乱。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/589763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Access数据库C#读写验证

1、数据库简介 Access数据库是一个相当古老的文件型数据库&#xff0c;主打一个简单方便&#xff0c;没有复杂的安装过程&#xff0c;没有庞大的后端管理&#xff0c;整个数据库就是一个文件。可以像普通文件一样复制和修改&#xff0c;可以同时读写。 在小型系统中&#xff0c…

Xgboost分类模型的完整示例

往期精彩推荐 数据科学知识库机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归PySpark大数据处理详细教程 定义问题 UCI的蘑菇数据集的主要目的是为了分类任务&#xff0c;特别是区分蘑菇是可食用还是有毒。这个数据集包含了蘑菇的各种特征&#xff0c;如…

系统学习Python——装饰器:函数装饰器-[装饰器状态保持方案:外层作用域和非局部变量]

分类目录&#xff1a;《系统学习Python》总目录 我们在某些情况下可能想要共享全局状态。如果我们真的想要每个函数都有自己的计数器&#xff0c;要么像前面的文章那样使用类&#xff0c;要么使用Python3.X中的闭包函数&#xff08;工厂函数&#xff09;和nonlocal语句。由于这…

听GPT 讲Rust源代码--library/alloc

File: rust/library/alloc/benches/slice.rs 在Rust源代码中&#xff0c;rust/library/alloc/benches/slice.rs文件的作用是对&[T]类型&#xff08;切片类型&#xff09;进行性能基准测试。该文件包含了对切片类型的一系列操作的基准测试&#xff0c;例如切片迭代、切片排序…

0101包冲突导致安装docker失败-docker-云原生

文章目录 1 前言2 报错3 解决结语 1 前言 最近在学习k8s&#xff0c;前置条件就是要安装指定版本的docker&#xff0c;命令如下 yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.62 报错 file /usr/libexec/docker/cli-plugins/docker-buildx fr…

用 print 太慢了!强烈推荐这款Python Debug工具~

作为程序员&#xff0c;我们都深知调试&#xff08;Debug&#xff09;在编程过程中的重要性。 然而&#xff0c;使用传统的"print"语句进行调试可能效率较低&#xff0c;今天&#xff0c;笔者将推荐一款独具一格的Python调试工具——Reloadium。 Reloadium为IDE添加…

sparkstreamnig实时处理入门

1.2 SparkStreaming实时处理入门 1.2.1 工程创建 导入maven依赖 <dependency><groupId>org.apache.spark</groupId><artifactId>spark-streaming_2.12</artifactId><version>3.1.2</version> </dependency> <dependency…

C++初阶——基础知识(内联函数)

目录 1.内联函数 内联函数的示例代码 1.内联函数 是一种 C 中的函数定义方式&#xff0c;它告诉编译器在每个调用点上插入函数体的副本&#xff0c;而不是像普通函数那样在调用时跳转到函数体所在的地址执行。这样可以减少函数调用的开销&#xff0c;提高程序的执行效率。 …

从入门到精通,30天带你学会C++【第十天:猜数游戏】

目录 Everyday English 前言 实战1——猜数游戏 综合指标 游玩方法 代码实现 最终代码 试玩时间 必胜策略 具体演示 结尾 Everyday English All good things come to those who wait. 时间不负有心人 前言 今天是2024年的第一天&#xff0c;新一年&#xff0c;新…

计算机毕业设计——springboot养老院管理系统 养老院后台管理

1&#xff0c;绪论 1.1 背景调研 养老院是集医疗、护理、康复、膳食、社工等服务服务于一体的综合行养老院&#xff0c;经过我们前期的调查&#xff0c;院方大部分工作采用手工操作方式,会带来工作效率过低&#xff0c;运营成本过大的问题。 院方可用合理的较少投入取得更好…

声明式导航传参详情

1 动态路由传参 路由规则path ->/article/:aid 导航链接 <router-link to"/article/1">查看第一篇文章</router-link> 组件获取参数: this.$route.params.aid 如果想要所有的值&#xff0c;就用this. $route. params 注意&#xff1a;这两个必须匹配…

Spring Cloud Function SpEL注入漏洞(CVE-2022-22963)分析

一、概述 2022年3月24日&#xff0c;Pivotal修补了Spring Cloud Function中一个关键的服务器端代码注入漏洞&#xff08;Spring表达式语言注入&#xff09;&#xff0c;该漏洞有可能导致系统被攻击。Spring是一种流行的开源Java框架&#xff0c;该漏洞与另一个相关的远程代码执…

Dirichlet Process (徐亦达老师)狄利克雷过程

混合高斯模型的例子 混合高斯模型 混合高斯模型&#xff08;Mixture of Gaussians&#xff0c;简称GMM&#xff09;是一种概率模型&#xff0c;用于对复杂的数据分布进行建模。它是由多个高斯分布组合而成的混合模型&#xff0c;每个高斯分布&#xff08;称为组件&#xff09;…

知识库问答LangChain+LLM的二次开发:商用时的典型问题及其改进方案

前言 如之前的文章所述&#xff0c;我司下半年成立大模型项目团队之后&#xff0c;我虽兼管整个项目团队&#xff0c;但为让项目的推进效率更高&#xff0c;故分成了三大项目组 第一项目组由霍哥带头负责类似AIGC模特生成系统第二项目组由阿荀带头负责论文审稿GPT以及AI agen…

pytorch深度学习笔记(共计169页,基于本人听完B站小土堆PyTorch深度学习快速入门教程所写)

一、笔记视频 pytorch深度学习&#xff08;共计169页&#xff0c;基于本人听完B站小土堆PyTorch深度学习快速入门教程所写&#xff09; 二、获取方式 方式一&#xff1a; 点击下面的链接 pytorch深度学习笔记 如果链接无法打开 直接复制下方链接即可 https://mall.bilibili.c…

如何借助边缘网关打造智慧配电房安全方案

配电房是电力系统的重要组成部分&#xff0c;通常设置有各种高压配电装置和箱柜&#xff0c;是企业安全管理的重点。传统的人工巡检和监控总是难以避免疏漏&#xff0c;导致风险隐患的产生和扩大。 随着物联网、边缘计算、设备联动控制等技术的普及应用&#xff0c;佰马针对配电…

在FC中手工创建虚拟机模板

1、Linux去除个性化信息 &#xff08;1&#xff09;编辑网卡配置文件&#xff0c;只保留以下内容&#xff08;以RHEL 7为例&#xff09; &#xff08;2&#xff09;清除主机密钥信息&#xff08;开机会自动生成&#xff09; &#xff08;3&#xff09;清除Machine ID&#xff…

机器学习概述

最近在学习机器学习的基础知识&#xff0c;在此记录一下 目前最火的机器学习框架是Scikit-Learn和pytorch&#xff0c;因此&#xff0c;之后的一段时间会使用这两种框架搭建机器学习的模型&#xff0c;相应的学习资源也会开源&#xff0c;希望可以学习到很多知识。 简单介绍机…

Servlet见解3

13 Cookie和Session http协议是一个无状态的协议&#xff0c;你每一个跳转到下一个页面的时候都是需要先登录才能使用&#xff0c;这样就很麻烦比如淘宝&#xff0c;没有cookie和session的话&#xff0c;用户在首页已经登录上去了&#xff0c;但是需要再次登录才能选择商品&am…

使用pyqt5+qtdesign设计模仿网易云音乐客户端界面

案例效果图 设计界面效果图&#xff1a; 运行效果图&#xff1a; 本项目目前只是对界面进行了设计&#xff0c;功能都没有进行完善&#xff0c;想完善的小伙伴自己拿到UI文件之后&#xff0c;自己完善即可。 简要设计思路说明 使用QFrame将界面分割布局成如下几个部分&am…