本文主要通过文档形式使用C++中string类的常见接口进行介绍,然后我们自己实现一个string类
标准库中的string
使用库中的string类时,必须包含头文件:#include<string>, 以及 using namespace std
string 构造函数
首先我们来看构造函数,在库函数中,string类给我们提供了多达七个构造函数接口
在这里我们主要介绍四个常见的构造:
1.string() 构造空的string类对象,即空串
当我们进行调试时可以看到,string()的确构造了一个空串:
在类与对象中我们也以及了解到,构造函数会对对象进行初始化操作,在这里s1的大小和最大容量被成功初始化!
2. string(const char*) 用string类对象来构造string类对象
在这里,我们将字符串Hello world来构造string对象,运行并调试,可以看到s1已经被字符串成功构造
3. string(const string&s) 拷贝构造函数
拷贝构造函数是使用同类对象初始化创建对象,也就是用已经存在的对象取创建一个还未创建的对象
注意:需要理清 拷贝构造 和 赋值拷贝 !!!
拷贝构造是用一个已经存在的对象来对创建一个还未被创建的对象
赋值拷贝是用一个已经存在的对象来给一个已经存在的对象进行赋值
int main()
{string s1("Hello world");//拷贝构造,s2还没被创建,用s1来创建对象s2string s2(s1);string s3;//赋值拷贝,s3在上面已经被创建,s2的值赋给s3s3 = s2;//s1,s2,s3的结果是一样的cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}
4. string(size_t n,char c)
string类对象中包含n个字符c,通俗的来讲,就是用n个字符c来构造对象
这个构造函数用的不多,在这里就不多赘述
迭代器
在C++中有迭代器这个东西,它其实是个像指针一样的对象,用法也和指针也很相似,但是迭代器并不是指针!!!
auto关键字
在编程时使用auto,可以提高我们的编写效率,但是也有缺陷。
1.auto可以自动推导变量类型,但是必须始终推导为同一类型
a时int类型,auto会根据a的类型自动推导b的类型,c会根据b的类型进行推导
也就是:
int(a)--->int(b)--->int(c)
2.包含auto的符号必定要有初始设定值,不然它就不会推导了
3.auto声明指针时,auto和auto*是没有区别的
4.auto不能作为函数的参数,但是可以作为函数的返回值
5.auto不能直接用来声明数组
范围for
适用于容器遍历和数组遍历,范围for会自动迭代,自动取数据,自动判断结束
自动取容器的数据赋值给左边的对象,自动++,自动判断结束
注意:迭代器变量出了范围for后生命周期就结束了,本质上并没有改变原对象,如果我们想通过范围for修改原对象,,需要加上引用
string 类对象的容量操作
在这里只讲解常用的容量操作接口
1.size() 返回字符串的有效长度
返回的单位是字节,返回的长度不一定等于最大容量!
size和length都是返回字符串有效长度,底层实现原理也相同,但是基本都是使用size()
2.resize() 将有效字符的个数改成n个,多出的空间用字符c填充
3.empty() 判断是否为空串
返回类型是bool,只作简单的空串判断
4.clear() 清空有效字符
clear只做简单的有效字符清空工作,返回值为空
5.reserve() 调整/预留空间
对于一个string类,类成员有 size(当前串的有效长度) 和 capacity(最大容量),那么这就意味着当我们对string对象进行字符串追加时,有可能会遇到最大容量扩容的问题,要知道扩容是会消耗性能的,如果我们创造一个长度非常夸张的string对象,那么扩容的次数可能会直线上升,为了解决这一问题,string类提供了一个reserve接口,能让我们自己创建string对象时调整最大容量
注意,reserve并不会改变原本字符串的有效个数,仅仅改变最大容量
如果预知一个串非常大的情况下,利用reserve提前开空间避免扩容,减少了性能的消耗
如果reserve的参数小于string的底层空间总大小时,那么此时reserve不会改变最大容量
string 类对象的访问和遍历
string类对象本质上就是字符串,在数据结构上是顺序表,顺序表的底层结构是数组,我们可以利用看待数组的思维来对待string类对象。
string类对象的访问和遍历,和顺序表的访问和遍历没有什么区别,通过下标或者指针均可
1.begin() 获取一个字符的迭代器
2.end() 获取最后一个字符的下一个位置的迭代器
end获得的不是最后一个字符的位置,而是最后一个字符的下一个位置!end()-1才是最后一个字符的位置
3.operator[ ] 返回pos位置的字符
在string类中,[ ]运算符重载,使其能像数组一样通过下标获取字符,pos位置一定要合法!
4.范围for
前面介绍范围for时已经讲解,不再重复
string类对象的修改操作
1.push_back 在字符串后尾插字符
尾插字符后,字符串的长度+1
2.append 字符串后追加字符串
append可以在字符串后追加字符串,也可以追加对象
append也可以在字符串后填充n个字符
append的使用也可以带上迭代器一起使用,按相同的顺序附加范围 [first,last) 中的字符序列的副本。
3.operator+= 字符串后追加字符串str
在string类中,+=符号进行了运算符重载,实现了字符串追加的功能
我们可以通过+=追加string对象,字符串或者单个字符,在OJ题中这是个常用的接口
4.c_str 返回C格式字符
返回一个指向数组的指针,此数组包含构成字符串对象值的相同字符序列,以及末尾的附加终止 null 字符 ('\0')
注意:返回的是一个被const修饰的指针!
5.replace 替换字符串的一部分
不建议常使用,如果是一个字符替换成另一个字符还好,不会有空间位置的挪动
6.find 在字符串中搜索由其参数指定的序列的第一个匹配项。
当然,find也能用来寻找串
7.rfind 从后面倒着找
我们知道,当我们需要判断一个文件是什么类型时,都是看它的后缀,但可曾想,一个文件有多个后缀,如Helloworld.txt.zip,.zip才是它真正的文件类型,这时候从后倒着找就非常的方便了
而关于rfind的使用,结合下面substr一起看
8.substr 在str中从pos位置开始,截取n个字符,然后将其返回
如果在参数中没有写明截取字符的个数,默认截取到字符串的末尾
substr和rfind的联合使用,对查找文件类型非常的高效,代码也非常的简洁明了
9.insert 在字符串pos位置插入字符串
10.erase 擦除字符串的一部分,减少其长度
刚刚我们通过insert插入了一串字符,我们也可以通过erase擦除字符串的一部分
string类对象的非成员函数
而有关非成员函数,这里只介绍一个getline
getline
有两个字符串,需要你存数据:
字符串一:Hello world!
字符串二:Helloworld!
可是当我们想往这两个串里cin数据时,却根本达不到想要的效果 ,因为当我们按下空格时,编译器默认认为我们已经完成了对串的输入,转而进行下一个串的输入,也就是说,当我们使用cin时无法存储空格字符
这时候就时getline展现的时候了,getline不仅可以将空格存入字符串中,还能自定义终止输入符
现在是2024年11月15日下午16:01
这篇博客其实还能补充很多内容,但是越写越累,索性不写了,缺的内容在以后的博客里填上,毕竟都周五下午了
有双休的打工人已经开始紧盯时间准备卡点下班,没双休的打工人已经开始幻想有双休的工作是怎么样的,而我这种清澈且愚蠢的大学生已经开始喃喃自语:我TM又活了一周!
有感而发:学习好啊,还是得学啊,图书馆的妹子真好看,这C++也越学越难受,上坡路走不完