第六章:string类

news2024/11/27 18:34:54

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 为什么学习string类
    • C语言中的字符串
    • ASCII
    • Unicode
      • **UTF-8**
      • UTF-16
      • UTF-32
    • GBK
  • 标准库中的string类
    • string类
      • 总结
    • string类的常用接口说明
      • 1. string类对象的常见构造
      • 2. string类对象的容量操作
      • 3. string类对象的访问及遍历操作
      • 4. string类对象的修改操作
      • 5. string类非成员函数
      • 6. string类对象的字符串的转换(在C++11适用)
  • vs和g++下string结构的说明
        • vs下string的结构
        • g++下string的结构


前言

string是字符序列的类


C++文档

为什么学习string类

C语言中的字符串

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

ASCII

ASCII (American Standard Code for Information Interchange):美国信息交换标准代码是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符。

**在计算机中存储和显示英语信息

26个大小写字母、数字、标点符号

建立一个符号和编码对应关系的映射表

用一个字节的大小存储7位编码,最高位不用,一个符号→一个字节**

在这里插入图片描述

int main()
{
	char str1[] = "apple";	

	char str2[] = "好好";

	cout << sizeof(str1) << endl;
		
	cout << sizeof(str2) << endl;

	return 0;
}

在这里插入图片描述

int main()
{

	char str2[] = "好好";

	cout << sizeof(str2) << endl;

	str2[3]--;
	cout << str2 << endl;

	str2[3]--;
	cout << str2 << endl;

	str2[3]++;
	cout << str2 << endl;
	
	str2[3]++;
	cout << str2 << endl;

	return 0;
}

在这里插入图片描述

Unicode

统一码(Unicode),也叫万国码单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。

统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求

UTF-8

UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。统一码的最大码位0x10FFFF也只有21位。

在这里插入图片描述

UTF-16

UTF-16编码以16位无符号整数为单位。我们把统一码编码记作U。

UTF-32

UTF-32编码以32位无符号整数为单位。统一码的UTF-32编码就是其对应的32位无符号整数。

GBK

GBK全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification)。

GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。
在这里插入图片描述

标准库中的string类

string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

string类的文档

在这里插入图片描述

string类用utf-8编码,按单字节处理
u16string用utf-16编码
u32string用utf-32编码
wstring类按两字节处理

在这里插入图片描述

编码:
计算机中存储只有二进制0、1,用对应的ASCII表来表示文字(支持英文的)其中ASCII表是对256个值建立一个对应的表示值
在早期只有欧美国家使用计算机(早期的计算机中只能表示英文,不能表示其他国家的文字),后来全世界各个国家都开始用计算机了,需要建立自己的编码表
在Linux中常用utf-8、utf-16、utf-32
在Windows中常用gbk

总结

  1. string是表示字符串的字符串类

  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;

  4. 不能操作多字节或者变长字符的序列。

  5. 在使用string类时,必须包含#include头文件以及using namespace std;

string类的常用接口说明

string类的常用接口

1. string类对象的常见构造

(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
void Teststring()
{
    string s1; // 构造空的string类对象s1
    string s2("hello bit"); // 用C格式字符串构造string类对象s2
    string s3(s2); // 拷贝构造s3
}

2. string类对象的容量操作

函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小,但不包含’\0’
empty (重点)检测字符串释放为空串,是返回true,否则返回false
clear (重点)清空有效字符
reserve (重点)为字符串提前预留空间
resize (重点)将有效字符的个数该成n个,多出的空间用字符c填充

在这里插入图片描述

注意:
1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
5. 在Windows中容量是以大约1.5倍增容的,在Linux中容量是以大约2倍增容的
6. reserve的作用:如果知道需要多少空间,直接一次性开好,避免增容,提高效率
7. resize的作用:既能开好空间,又能对这些空间初始化

string容量相关方法使用代码演示

3. string类对象的访问及遍历操作

函数名称功能说明
operator[] (重 点)返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置(‘\0’)的迭代器
rbegin + rendrbegin获取最后一个字符的迭代器 + rend获取开头一个字符前一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式,底层是用迭代器

string中元素访问及遍历代码演示

int main()
{
    string s1("hello world");
    string::iterator it = s1.begin();
    //正向迭代器
    while (it != s1.end())
    {
	    cout << *it << " ";
	    it++;
    }
	string::reverse_iterator rit = s1.rbegin();
    //反向迭代器
	while (rit != s1.rend())
	{
		cout << *rit << " ";
		rit++;
        //都是++
	}
  
    for (auto ch : s1)
	{
		cout << ch << " ";
	}

	cout << endl;
  
	return 0;
}
void Func1(const string& s)
{	
	//遍历和读容器的数据,不能写
	//string::const_iterator it = s.cbegin();
    auto it = s.cbegin();
    //静态正向迭代器
	while (it != s.end())
	{
		cout << *it << " ";
        it++;
	}

	cout << endl;
}
void Func2(const string& s)
{	
    
	//string::const_reverse_iterator it = s.crbegin();
    auto it = s.crbegin();
    //静态反向迭代器
	while (it != s.rend())
	{
		cout << *it << " ";
        it++;
	}

	cout << endl;
}
int main()
{
	string s1("hello world");
	string::iterator it = s1.begin();
    //iterator 迭代器 是属于类的一种类型
	while (it != s1.end())
	{
		cout << *it << " ";
		it++;
	}

	for (auto ch : s1)
	{
		cout << ch << " ";
	}
    
    Func1();
    
    Func2();

	cout << endl;
	
	return 0;
}

总结:
迭代器是一个行为像指针的东西,有可能是指针,也有可能不是指针
迭代器可以用统一类似的方式去访问修改容器
begin()返回的是第一个有效数据位置的迭代器,end()返回的是最后一个有效数据的下一个位置的迭代器
rbegin()返回的是最后个有效数据位置的迭代器,rend()返回的是第一个有效数据的前一个位置的迭代器
所有的容器都支持用迭代器,所以迭代器才是容器通用的访问方式(vector/string这样的结构支持下标+[]去访问,而像list、map这样的就不支持了),虽然迭代器在所有数据结构都是可以使用的,但[]+下标指适用顺序表。
const对象要用const迭代器,只读,不能写
operator[]和at的区别:operator[]如果发生越界访问会报断言错误(assert),而at会报异常(需要捕获异常)

4. string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

string中插入和查找等使用代码演示

注意:
1. 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

int main()
{
	string s1("world");

	s1.insert(0, "hello");

	//不推荐使用insert,效率低
	//s1.insert(5, 1, ' ');
	//s1.insert(5, " ");
	string::iterator it = s1.begin();
	s1.insert(it+5, ' ');
	cout << s1 << endl;
	return 0;
}
int main()
{
	//不推荐使用erase,效率低
	string s1("hello world");
	//s1.erase(5, 1);

	string::iterator it = s1.begin();
	//s1.erase(it + 5);

	//s1.erase(5);
	s1.erase(5, 6);
	cout << s1 << endl;

}
int main()
{
	//string s1("hello world");
	//s1.replace(5, 1, "%%d");//扩容+移动数据
	//cout << s1 << endl;、

	string s1("hello world i love you");
	size_t num = 0;
	for (auto ch : s1)
	{
		if (ch == ' ')
		{
			num++;
		}
	}
	//提前开空间,避免replace时扩容
	s1.reserve(2* num + s1.size());
	size_t pos = s1.find(' ');
	while(pos != string::npos)
	{	
		s1.replace(pos, 1, "%20");
		pos = s1.find(' ', pos + 3);
	}
	cout << s1 << endl;
}

//空间换时间
int main()
{
	string s1("hello world i love you");
	string newStr;
	size_t num = 0;
	for (auto ch : s1)
	{
		if (ch == ' ')
		{
			num++;
		}
	}
	//提前开空间,避免replace时扩容
	s1.reserve(2* num + s1.size());
	for (auto ch : s1)
	{
		if (ch != ' ')
			newStr += ch;
		else
			newStr += "%20";
	}
	s1 = newStr;
	cout << newStr << endl;
}
int main()
{
	string s1("xxx");
	string s2("yyy");

	s1.swap(s2);
	cout << s1 << endl;
	cout << s2 << endl;

	swap(s1, s2);
	cout << s1 << endl;
	cout << s2 << endl;
	 
}

在这里插入图片描述

5. string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)输入运算符重载
operator<< (重点)输出运算符重载
getline (重点)获取一行字符串
relational operators (重点)大小比较

在这里插入图片描述

在这里插入图片描述

cin遇到空格和换行就会分割(或结束),而getline遇到空格不会分割(或结束)遇到换行才分割(或结束)

6. string类对象的字符串的转换(在C++11适用)

在这里插入图片描述

vs和g++下string结构的说明

注意:下述结构是在32位平台下进行验证,32位平台下指针占4个字节.

vs下string的结构

string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间:

  • 当字符串长度小于16时,使用内部固定的字符数组来存放

  • 当字符串长度大于等于16时,从堆上开辟空间

union _Bxty
{ // storage for small buffer or pointer to larger one
	value_type _Buf[_BUF_SIZE];
	pointer _Ptr;
	char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。
其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量最后:还有一个指针做一些其他事情。
故总共占16+4+4+4=28个字节。
在这里插入图片描述

g++下string的结构

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指针将来指向一块堆空间,内部包含了如下字段:

  • 空间总大小

  • 字符串有效长度

  • 引用计数

struct _Rep_base
{
	size_type        _M_length;
	size_type        _M_capacity;
	_Atomic_word      _M_refcount;
};
  • 指向堆空间的指针,用来存储字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1uFFi6yM-1689733417126)(https://flowus.cn/preview/cc560c88-e3f5-4381-b6fc-3a21c3afb6f4)]

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

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

相关文章

亚马逊云科技十年出海经验,为中国企业提供跨越式发展

对于一座优秀的港口而言&#xff0c;不仅要求其所在的地理位置得天独厚以及拥有庞大的货运船舶吞吐量&#xff0c;能否为地区带来良好的发展生态&#xff0c;提供和创造新的就业机会也是重要的考量。对于很多中小企业而言&#xff0c;他们不具备大型企业的体量&#xff0c;在海…

vscode(Better Comments插件)在vue文件中不显示相对应的颜色

解决办法&#xff1a; 1、在.vscode文件下找到 aaron-bond.better-comments-3.0.2 &#xff08;我的路径&#xff1a;C:\Users\cown\.vscode\extensions\aaron-bond.better-comments-3.0.2&#xff09;&#xff0c;后面版本不唯一&#xff0c;根据自身情况辨别 2、进入文件路…

HTTPS概念wireshark分析

目录 密钥&加密算法CA & 数字证书https流程连接流程springboot项目启动httpswireshark分析https流程 密钥&加密算法 密钥&#xff1a;通常是一个字符串或数字&#xff0c;进行加密/解密算法时使用。公钥和私钥都是密钥&#xff0c;只不过一般公钥是对外开放的&…

如何在 Endless OS 上安装 ONLYOFFICE 桌面编辑器

ONLYOFFICE 桌面编辑器是一款基于依据 AGPL v.3 许可进行分发的开源办公套件。使用这款应用&#xff0c;您无需保持网络连接状态即可处理存储在计算机上的文档。本指南会向您介绍&#xff0c;如何在 Endless OS 上安装 ONLYOFFICE 桌面编辑器。 ONLYOFFICE 桌面版是什么 ONLYO…

Sencha ExtJS v1.0.4 扩展不能“转到定义“的解决办法

VSCode 的 Sencha 扩展自动更新到了 1.0.4&#xff0c;去除激活提示的方法和以前一样。 但是有扩展bug&#xff0c;就是无法转到定义&#xff0c;打开 VSCode 的开发者工具&#xff0c;由一堆报错。 解决办法&#xff1a;要修改下文件 C:\Users\xxx\.vscode\extensions\sench…

谷歌黑客语法与漏洞寻找

谷歌黑客语法与漏洞寻找 一、常见的搜索引擎二、Google部分语法三、通配符四、FOFA五、Shodan六、例子&#xff1a;常见的后台地址 一、常见的搜索引擎 浏览器 浏览器是用来检索、展示以及传递Web信息资源的应用程序。 搜索引擎 所谓搜索引擎&#xff0c;就是根据用户需求与一…

惊艳!AI创意字体真绝了;6道AIGC高频面试题与解答;为啥语音助手还没集成LLM;深度学习算法红宝书 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 惊艳&#xff01;手把手教你使用 Stable Diffusion 制作AI创意字体 最近AI创意字体刷爆了 ShowMeAI 社群&#xff01;伙伴们纷纷惊叹这…

OJ练习第139题——模拟行走机器人

模拟行走机器人 力扣链接&#xff1a;874. 模拟行走机器人 题目描述 机器人在一个无限大小的 XY 网格平面上行走&#xff0c;从点 (0, 0) 处开始出发&#xff0c;面向北方。该机器人可以接收以下三种类型的命令 commands &#xff1a; -2 &#xff1a;向左转 90 度 -1 &…

Pytorch:搭建卷积神经网络完成MNIST分类任务

2023.7.18 MNIST百科&#xff1a; MNIST数据集简介与使用_bwqiang的博客-CSDN博客 数据集官网&#xff1a;MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges MNIST数据集获取并转换成图片格式&#xff1a; 数据集将按以图片和文件夹名为标签的…

青岛大学_王卓老师【数据结构与算法】Week05_13_队列的顺序表示和实现1_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

DeepSpeed系列篇1:零门槛上手DeepSpeed实战(服务器部署及训练过程详解SFT)

1、建立虚拟环境 conda create -n dsnew python3.10 2、安装pytorch conda install pytorch torchvision torchaudio pytorch-cuda11.7 -c pytorch -c nvidia 3、安装deepspeed pip install deepspeed 4、下载DeepSpeedExamples并安装依赖 https://github.com/microsof…

一文了解DDD分层架构演进

1.3 分层架构演进 1.3.1 传统四层架构 将领域模型和业务逻辑分离出来&#xff0c;并减少对基础设施、用户界面甚至应用层逻辑的依赖&#xff0c;因为它们不属业务逻辑。将一个夏杂的系统分为不同的层&#xff0c;每层都应该具有良好的内聚性&#xff0c;并且只依赖于比其自身更…

arduinoIDE2.1.1最新版升级开发板(esp32-2.0.3升级2.0.10)方法总结(esp8266升级通用)

一、arduinoIDE 升级最新版 2.1.1方法 1.1.通过IDE2.x直接升级(推荐,速度还可以) 1.2.官网下载安装包覆盖升级(地址https://www.arduino.cc/en/software) 1.3 ESP8266升级方法雷同可参考(原理一样,最新好像是3.1.2) https://github.com/esp8266/Arduino/releases http…

C++入门知识点

目录 命名空间 命名空间定义 命名空间使用 法一&#xff1a;加命名空间名称及作用域限定符&#xff1a;&#xff1a; 法二&#xff1a;使用using部分展开&#xff08;授权&#xff09;某个命名空间中的成员 法三&#xff1a;使用using对整个命名空间全部展开&#xff08;授权…

Windows修改mysql服务的root密码

目录 步骤1、停止mysql服务2、使用命令行启动mysql服务&#xff0c;跳过密码验证3、密码置空4、关闭命令行启动的mysql服务并正常启动5、修改root密码 参考 步骤 1、停止mysql服务 以管理员身份打开终端&#xff0c;输入指令net stop mysql停止MySQL服务&#xff0c;停止服务…

PBOOTCMS登录请求发生错误,您可按照如下方式排查: 1、试着删除根目录下runtime目录,刷新页面重试;2、检查系统会话文件存储目录是否具有写入权限;

PBOOTCMS后台登录请求发生错误&#xff0c;您可按照如下方式排查&#xff1a; 1、试着删除根目录下runtime目录&#xff0c;刷新页面重试;2、检查系统会话文件存储目录是否具有写入权限&#xff1b; 以上提示其实就是&#xff0c;表单提交校验失败&#xff0c;请刷新后重试的提…

U盘文件修复怎么做?简单3步,快速修复u盘文件!

“很离谱&#xff01;由于有些文件存在错误&#xff0c;我想将这些错误文件修复&#xff0c;但在操作过程中&#xff0c;不知为什么所有的数据都被删除了。U盘文件修复应该怎么做呀&#xff1f;是不是我的操作方法有误呢&#xff1f;” U盘使用时间长了之后&#xff0c;很可能会…

【分布鲁棒、状态估计】分布式鲁棒优化电力系统状态估计研究[几种算法进行比较](Matlab代码实现)

&#x1f4a5;1 概述 文献来源&#xff1a; 摘要&#xff1a; 能源市场的自由化、可再生能源的渗透、先进的计量能力以及对情境感知的需求&#xff0c;都要求进行系统范围的电力系统状态估计&#xff08;PSSE&#xff09;。然而&#xff0c;由于互联的复杂性、实时监测中的通信…

MySQL八股学习记录6-日志from小林coding

MySQL八股学习记录6-日志from小林coding MySQL日志分类undo logBuffer Poolredo logbinlogredo log 和undo log有什么区别主从复制是如何实现update语句执行过程为什么需要两阶段提交 MySQL日志分类 undo log:InnoDB存储引擎层生成的日志,实现事务中的原子性,主要用于事务回滚…

学习记录——SpectFormer、DilateFormer、ShadowFormer、MISSFormer

SpectFormer: Frequency and Attention is what you need in a Vision Transformer, arXiv2023 频域混合注意力SpectFormer 2023 论文&#xff1a;https://arxiv.org/abs/2304.06446 代码&#xff1a;https://badripatro.github.io/SpectFormers/ 摘要视觉变压器已经成功地应用…