C++中string类的基本用法

news2024/11/16 3:37:40

文章目录

  • 一、string的默认成员函数
    • 1. 构造函数
    • 2.赋值重载
  • 二、string的常见容量操作
    • 1.size、length、capacity
    • 2.clear
    • 3.empty
    • 4. reserve
    • 5. resize
  • 三、string的访问及遍历操作
    • 1. operator[]
    • 2. 迭代器
    • 3. 范围for
  • 四、string的修改操作
    • 1. push_back
    • 2. append
    • 3. operator+=
    • 4. c_str
  • 五、string的非成员函数重载
    • 1. operator+
    • 2. operator>>和operator<<
    • 3. getline
    • 4. relational operators


一、string的默认成员函数

在这里插入图片描述

1. 构造函数

在这里插入图片描述
我们可以看到在C++98中光构造函数就有7个重载,其中框住的三个是需要重点掌握的,下面分别演示一遍。

string();// 构造一个空字符串
string (const char* s);// 用C-string来构造string类对象
string (const char* s, size_t n);// 用C-string的前n个字符来构造string类对象
string (size_t n, char c);// 生成n个c字符的字符串
string (const string& str);// 利用原先的字符串做拷贝构造
// 拷贝str字符串中从pos位置开始的len个字符
string (const string& str, size_t pos, size_t len = npos);

在这里插入图片描述


2.赋值重载

在这里插入图片描述

string& operator= (const string& str);// 将一个string对象赋值给到另一个
string& operator= (const char* s);// 将一个字符串赋值给到string对象
string& operator= (char c);// 将一个字符赋值给到string对象

在这里插入图片描述


二、string的常见容量操作

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

1.size、length、capacity

  • 【size】和【length】代表的含义一样都是表示字符串中有几个字符,而【capacity】则表示容量为多少。比如一个教室做多容纳50个学生,现在教室里有20个学生。这里的50就代表是容量【capacity】这里的20就代表【size】和【length】。
  • 可以看到s一共有13个字符(其中包含一个空格),所以【size】和【length】的值为13,而capacity的值为15。这里capacity的值是会随之你插入字符的增多自动扩容的。
    在这里插入图片描述
  • 有人会问那【size】和【length】表示的含义是一样的,那有一个不就行了,为什么还要设计出两个来呢?那是因为【size】是STL中的接口,string出现的比STL要早,也就是说刚开始string只有【length】这个接口,但在STL出来之后为了接口的统一,string就又加上了【size】。

下面我们来探究一下【capacity】

void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

在这里插入图片描述

  • 我们可以看到在vs中是1.5倍的扩容逻辑
    在这里插入图片描述
  • 在Linux中是两倍的扩容逻辑
  • 这是因为不同平台下这个STL库的内部实现是不一样的,甚至都是在VS中,使用不同版本的VS也会导致扩容大小不同。

2.clear

【clear】的作用就是将字符串清空将【size】改为0,那它还有什么细节呢?我们用下面的函数进行测试。

void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, bit!!!");
	cout <<"clear前size:" << s.size() << endl;
	//cout << s.length() << endl;
	cout << "clear前capacity:" << s.capacity() << endl;
	cout << s << endl;

	// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
	s.clear();
	cout << "clear后size:" << s.size() << endl;
	cout << "clear后capacity:" << s.capacity() << endl;

}

在这里插入图片描述

  • 可见对于clear来说,它只会清空字符串中的【size】原来是13,现在清空了变成了0,但对于【capacity】来说是不会有什么变化的,原来是15现在还是15。如果你是这个接口的实现者一定不会去清空这个【capacity】容量的大小,万一后面又需要插入字符呢?此时又需要去进行一个扩容,是非常麻烦的。

3.empty

【empty】就是判断字符串是否为空,如果为空返回真(1),否则为假(0)。
在这里插入图片描述

  • 可见一开始不为空所以为假输出0,clear之后为空是真输出1。

4. reserve

【reserve】的功能是提前为一个字符串开好空间。
在这里插入图片描述

  • 可以看到在vs中我们提前用reserve开了空间之后就不会在进行扩容操作了。但是这里我们发现用的是reserve(100),开了一百个空间,但实际上vs却开了111个空间,而Linux中确实说开100就开100。究其原因还是平台不同底层实现不同。
    在这里插入图片描述

5. resize

void resize (size_t n);
void resize (size_t n, char c);		// 初始化数据为n个c字符

在这里插入图片描述
对于reserve来说只会改变capacity,size原来是多少就是多少不改变,但resize是二者都改变,size变成’n’,capacity遵循vs的扩容规则比n多一些。

  1. 如果 n > 当前的字符串长度,则在末尾插入所需数量的字符以达到n的大小来扩展当前内容,没有指定则填充’\0’。
  2. 如果n < 当前的字符串长度,则会去进行一个删除的操作,删除第n个字符之后的字符。

第一点上面已经验证,第二点如图,我们发现会出现截断字符的现象。
在这里插入图片描述

s.resize(100, 'a');//指定填充的字符为a

三、string的访问及遍历操作

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

1. operator[]

char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;

这个接口学过运算符重载的肯定不陌生,本质上就是对[]进行了重载,因此我们可以使用**下标加[]**的方式进行访问string中的数据。并且由于返回的是char类型的引用,因此我们可以直接通过下标加[]的方式进行修改数据。

在这里普通类型的会调用char& operator[] (size_t pos);,而const string s2会调用const类型的[]重载const char& operator[] (size_t pos) const;

void Teststring3()
{
	string s1("hello Bit");
	const string s2("Hello Bit");
	cout << s1 << " " << s2 << endl;
	cout << s1[0] << " " << s2[0] << endl;

	s1[0] = 'H';
	cout << s1 << endl;

	// s2[0] = 'h';   代码编译失败,因为const类型对象不能修改
}

在这里插入图片描述


2. 迭代器

下面我们要说以下迭代器,迭代器呢可以说是STL中很重要的一部分。简单来说迭代器就是用来遍历或访问容器中的数据的,我们暂时可以把迭代器想象成指针,通过指针的++或者–加解引用的方式,我们就可以遍历一个数组,或者访问数组中的元素。当然指针只是迭代器中的一种,迭代器要实现的目的就是通过++或者–能够遍历容器中所有的元素,我们数组是一段连续的空间,可以通过指针加一的方式遍历整个数组,但是如果是链表呢?这种情况下通过对每个指针++的操作就无法实现目的了,因此指针就不适合当迭代器了,我们就得封装新的迭代器。
在这里插入图片描述
在这之前呢,我们认识两个最常见的接口函数,即为begin和end

  • begin获取一个字符的迭代器
  • end获取最后一个字符下一个位置的迭代器


在这里插入图片描述
迭代器是是另一种访问string中内容的方式,图示如下,我们使用一个it去保存这个字符串【begin】处的位置,那么在其不断进行后移的过程中,就是在遍历这个字符串,当其到达最后的【end】处时,也就遍历完了,此刻便会停了下来。

void TestIterator()
{
	string s("abcdef");

	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

在这里插入图片描述

  • 迭代器也可以像数组那样在遍历的时候修改内部的元素,it取到的是每个元素的位置,那么对于*it来说即为每个元素
void TestIterator()
{
	string s("abcdef");
	string::iterator it = s.begin();
	while (it != s.end())
	{
		(*it)++;
		it++;
	}
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << endl;
		++it;
	}
}

在这里插入图片描述

begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器,而rbegin和rend恰恰相反,rbegin获取最后一个字符的迭代器 + rend获取第一个字符前一个位置的迭代器
也就是说用begin和end遍历是从前往后遍历,用rbegin和rend就是从后往前遍历。
要注意的地方就是定义要这样string::reverse_iterator rit = s.rbegin();,当然如果记不住这么一长串我们可以直接使用auto来进行自动推导。

void Teststring4()
{
	string s("abcdef");
	string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
	//auto rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << endl;
		rit++;
	}
}

在这里插入图片描述


3. 范围for

这里的auto我们以前介绍过,它可以自动推导类型,这里如果我们不用auto的话直接使用char也是可以的。

void TestRangeFor()
{
	string s("abcdef");

	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;
}

范围for的底层其实是迭代器,也就是在底层使用了迭代器进行遍历。如果没有迭代器,那就不能使用范围for。
也可以像迭代器那样在遍历的时候去做一个修改,值得注意的是要在ch后面加个引用,否则是达不到修改的目的的。
在这里插入图片描述


四、string的修改操作

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

1. push_back

在这里插入图片描述
就是在当前的字符串后面追加一个字符,值得注意的是只能追加一个字符,不能追加多个字符否则会报错。
在这里插入图片描述


2. append

在这里插入图片描述
这个函数重载了很多,大家可以根据下面的介绍自己操作一下。

string& append (const string& str);	// 追加一个string对象
// 追加一个string对象中的指定字符串长度
string& append (const string& str, size_t subpos, size_t sublen);	
string& append (const char* s);	// 追加一个字符串
string& append (const char* s, size_t n);// 追加字符串中的前n个字符串
string& append (size_t n, char c);// 追加n个字符

	string s1("aaaaa");
	string s2("bbbbb");
	s1.append(s2);
	cout << s1 << endl;
	s1.append(" ");

	s1.append("ccccc");
	cout << s1 << endl;
	s1.append(" ");

	s1.append("hello", 3);
	cout << s1 << endl;
	s1.append(" ");

	s1.append(10, 'e');
	cout << s1 << endl;

自已对照一下。
在这里插入图片描述


3. operator+=

在这里插入图片描述

  1. 拼接两个string类型的字符串
	s1 += s2;

在这里插入图片描述

  1. 拼接一个stirng类型加一个字符串
	s1+="world";

在这里插入图片描述
3. 拼接一个string类型加一个字符

s1+='w'

在这里插入图片描述


4. c_str

在这里插入图片描述
它的功能是返回一个c格式的字符串。有的人可能会说,为什么还要转换成C格式的字符串呢?那是因为我们调用某些函数,在传参的时候必须传的是c格式的字符串,不能传string,比如打开文件的fopen函数。

FILE * fopen ( const char * filename, const char * mode );

因此如果我们这样打开这个文件的话就会报错

void TestCStr()
{
	string str = "test.cpp";
	fopen(str, "r");
}

在这里插入图片描述
因此我们应该使用c_str函数进行转换,这个接口存在的意义就是一座桥,将C++和c关联起来。

FILE* fout =  fopen(str.c_str(), "r");

五、string的非成员函数重载

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

1. operator+

谈起operator+,不知道各位有没有想起operator+=呢?我们可以将二者对比一下。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二者的最本质区别还是在于这个效率问题,对于==operator+==而言,其底层在实现的时候因为无法对this指针本身造成修改,所以我们会通过拷贝构造出一个临时对象,对这个临时对象去做修改后返回,那我们知道返回一个出了作用域就销毁的对象,只能使用传值返回,此时又要发生一个拷贝因此本接口其实不太推荐读者使用,了解一下即可,尽量还是使用operator+= 来得好。


2. operator>>和operator<<

在这里插入图片描述
流提取,就是我们使用cin >>输入操作的时候一样,控制台要等待我们输入一个值
在这里插入图片描述
流插入,通过去缓冲区中拿取数据,然后将其显示在控制台上。
在这里插入图片描述


3. getline

使用getline我们可以从缓冲区获取一整行的数据
在这里插入图片描述
无论是C语言中的scanf还是C++中的cin每次遇到空格就会直接结束输入,那有没有一种方法在输入的时候遇到空格不结束遇到换行才结束呢?那就是可以使用getline函数。
在这里插入图片描述
第一个参数填cin,第二个填要输入的字符串就行。


4. relational operators

大小比较,这其实就是在底层将==、<、>等等这些运算符进行了重载。

==是将string中的每个字符进行对比,如果所有字符全都一样,那就返回true
<就是将两个字符串中的字符从第一个开始比大小,这里的比大小是按ASCII码进行比较,如果两个串s1和s2,其中s1第一个元素的ASCII码比s2第一个元素的ASCII码小那就返回true否则返回false并停止比较,如果s1和s2第一个字符相同,那就比较第二个字符,以此类推。

简单演示几个
在这里插入图片描述
由于ASCII码中b的比a的大,所以输出的是s1<s2。
在这里插入图片描述


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

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

相关文章

【软考设计师笔记】一篇文章带你了解数据库

【考证须知】IT行业高含金量的证书(传送门)&#x1f496; 【软件设计师笔记】计算机系统基础知识考点(传送门) &#x1f496; 【软件设计师笔记】程序语言设计考点(传送门) &#x1f496; 【软件设计师笔记】操作系统考点(传送门)&#x1f496; 【软件设计师笔记】什么是软…

校园圈子交友系统---在你身边的脱单神器!APP小程序H5,三端都有,源码交付,随意二开!

相比社会的交友环境&#xff0c;校园交友更加封闭也更容易成功&#xff0c;很多朋友都能在校园里找到和自己志同道合的伙伴&#xff0c;或者一段适合自己的缘分 有多种不同的聊天方法&#xff0c;语音&#xff0c;文本&#xff0c;视频&#xff0c;满足社会需求&#xff0c;软…

特征工程:特征构建

目录 一、前言 二、正文 Ⅰ.分类特征重新编码 ①分类特征 ②离散特征 ③多标签类别编码 Ⅱ.数值特征重新编码 ①多项式 ②多个变量的多项式特征 Ⅲ.文本数据的特征构建 ①文本词频条形图 ②词袋模型 ③TF-IDF矩阵 三、结语 一、前言 特征工程中的特征构建的主要目的是生…

记一次使用ASMLIB标记磁盘导致的数据库系统宕机案例

在对某医院HIS数据库环境搜集过程中&#xff0c;发现这套Oracle RAC数据库没有正确使用到multipath提供的多路径磁盘&#xff0c;本着对用户及合作伙伴负责的态度&#xff0c;将过程做一描述说明&#xff0c;以及提出一点解决问题的思路建议。 系统环境&#xff1a; 操作系统…

第八届:世界3D渲染挑战赛《无尽阶梯》正式开启

全世界的3D艺术创作者们引颈期盼的盛事“全球3D渲染艺术大奖赛”已迈入第八个年头。本届比赛的主题为“无尽的阶梯”&#xff0c;参赛者们可通过挑战赛展现自身的创造力&#xff0c;比赛在行业内拥有极高的知名度&#xff0c;含金量十足&#xff0c;参赛这可通过这里提高自己在…

[React] ref属性

简介 ref 即 reference &#xff0c;是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。 组件被调用时会新建一个该组件的实例&#xff0c;而 ref 就会指向这个实例。它可以是一个回调函数&#xff0c;这个回调函数会在组件被挂载后立即执行。 为了防止内存泄漏…

【C语言】贪吃蛇 详解

该项目需要的技术要点 C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32API等。 由于篇幅限制 和 使知识模块化&#xff0c; 若想了解 使用到的 Win32API 的知识&#xff1a;请点击跳转&#xff1a;【Win32API】贪吃蛇会使用到的 Win32API 目录 1. 贪吃蛇游…

配置Jenkins自动构建打包项目

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 需求说明 1、给A项目配置jenkins每2小时无条件自动构建一次&#xff0c;无论是否有代码提交。 2、给B项目配置jenkins每15分钟检…

如何在Mac上允许主流浏览器使用弹出式窗口?这里有详细步骤

这篇文章教你如何关闭流行的Mac浏览器上的弹出窗口阻止程序,包括Safari、Chrome和Firefox。它还探讨了你可能希望这样做的原因及其影响。 如何在Mac上允许Safari使用弹出窗口 如果你经常在Mac上使用Safari,你会注意到默认情况下弹出窗口阻止程序是打开的。有时,这并不方便…

Python进阶----在线翻译器(Python3的百度翻译爬虫)

目录 一、此处需要安装第三方库requests: 二、抓包分析及编写Python代码 1、打开百度翻译的官网进行抓包分析。 2、编写请求模块 3、输出我们想要的消息 三、所有代码如下&#xff1a; 一、此处需要安装第三方库requests: 在Pycharm平台终端或者命令提示符窗口中输入以下代…

Springboot集成jasypt实现配置文件加密

Jasypt它提供了单密钥对称加密和非对称加密两种加密方式。 单密钥对称加密&#xff1a;一个密钥加盐&#xff0c;可以同时用作内容的加密和解密依据&#xff1b; 非对称加密&#xff1a;使用公钥和私钥两个密钥&#xff0c;才可以对内容加密和解密&#xff1b; 我们以单密钥对称…

鸿蒙内核框架

1 内核概述 内核简介 用户最常见到并与之交互的操作系统界面&#xff0c;其实只是操作系统最外面的一层。操作系统最重要的任务&#xff0c;包括管理硬件设备&#xff0c;分配系统资源等&#xff0c;我们称之为操作系统内在最重要的核心功能。而实现这些核心功能的操作系统模…

Android ImageView 设置圆角及外边框样式

github地址&#xff1a;GitHub - WeiLianYang/RoundImageView: &#x1f525;&#x1f525;&#x1f525;用于设置 ImageView 的 圆角、外边框颜色、外边框宽度 添加依赖 repositories {mavenCentral() } implementation io.github.weilianyang:RoundImageView:1.0.2 效果预…

Dijkstra算法(求最短路)

简介&#xff1a; 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的&#xff0c;因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法&#xff0c;解决的是有权图中最短路径问题。 特点&#xff1a; 迪杰斯特拉算法采用的是一种贪心策略&a…

nginx简单配置四种携带/时的拼接关系

代理静态文件&#xff08;代理路径后缀与被代理的路径后缀不相同&#xff09; 1、 当 location 尾部有 /&#xff0c;且代理地址尾部也有 / 时&#xff1a; location /test11/ {root /usr/local/nginx/html/; } 则访问 http://ip/test11/aaa&#xff0c;实际访问的是/us…

Linux环境下配置mysql主从复制

主从配置需要注意的地方 1、主DB server和从DB server数据库的版本一致 2、主DB server和从DB server数据库数据一致[这里就会可以把主的备份在从上还原&#xff0c;也可以直接将主的数据目录拷贝到从的相应数据目录] 3、主DB server开启二进制日志,主DB server和从DB serve…

使用esp32 cam + SR602人体感应模块制作一个小型的监控

需求&#xff1a; 做一个小型的监控&#xff0c;类似电子猫眼&#xff0c;监测到人之后&#xff0c;取一张图 然后发送到自己的邮箱。 架构&#xff1a; 1.sr602 传感器监测到人 2. esp32 cam 取图 并通过mqtt协议传到远端服务器 3, 服务器利用python 搭建一个mqtt客户端&…

dump分析方法

一、关于dump 1、什么是dump 在计算机领域中&#xff0c;术语“dump”通常用来指代将某种数据以某种格式进行转储或导出的过程。这个术语可以用于多种不同的上下文&#xff0c;下面是一些常见的情况&#xff1a; 内存转储&#xff08;Memory Dump&#xff09;&#xff1a;在…

GRUB2 致力于 TPM2 自动磁盘解锁、TrenchBoot 等

Oracle 的 Daniel Kiper 提供了当前 GRUB 引导加载程序开发活动的状态更新、未来展望以及预计在 11 月份发布下一个版本的计划。 Kiper 本周末出席了在布鲁塞尔举行的 FOSDEM 2024&#xff0c;再次提供有关 GRUB 的状态更新。 早在 12 月&#xff0c;GRUB 2.12 就发布了&#…

09_树莓派_树莓派外设板_GPIO_按键的中断与消抖

目录 1.树莓派外设集成板总体介绍 2.第一部分 按键矩阵 GPIO_按键与中断 3.实现效果 1.树莓派外设集成板总体介绍 1&#xff09;前言&#xff1a;这是一块为了验证树莓派【兼容树莓派多个型号】的40pins的外设接口的外接板&#xff0c;告别复杂的面包板外设搭建。【欢迎各位…