1. 为什么学习string类?
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。
在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本 都使用string类,很少有人去使用C库中的字符串操作函数。
2. 标准库中的string类
2.1 string类(了解)
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架。
string比STL出现的还要早,所以不包含在contain的类别里面,但也算是一种数据结构。
1. 字符串是表示字符序列的类
2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。
3. string 类是使用 char( 即作为它的字符类型,使用它的默认 char_traits 和分配器类型 ( 关于模板的更多信息,请参阅basic_string) 。
4. string 类是 basic_string 模板类的一个实例,它使用 char 来实例化 basic_string 模板类,并用 char_traits和allocator 作为 basic_string 的默认参数 ( 根于更多的模板信息请参考 basic_string) 。
5. 注意,这个类独立于所使用的编码来处理字节 : 如果用来处理多字节或变长字符 ( 如 UTF-8) 的序列,这个类的所有成员( 如长度或大小 ) 以及它的迭代器,将仍然按照字节 ( 而不是实际编码的字符 ) 来操作。
总结:
1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string string。
4. 不能操作多字节或者变长字符的序列。
在 使用 string 类时,必须包含 #include 头文件以及 using namespace std ;
2.2 string类的常用接口说明
2.2.1string的构造
首先给大家介绍无参的string构造,以及使用字符串构造,还有拷贝构造这三种最常用的构造方式。如果想打印string类的对象直接使用cout即可,因为string类重载了流插入和流提取。
int main() { //string(),构造空的string类对象s1 string s1; //string(const char* s),用C格式字符串构造string类对象s2 string s2("hello world"); //string(string s),拷贝构造s3 string s3(s2); cout<<s3<<endl; return 0; }
2.2.2string的析构
string相当于是一个管理字符串的顺序表,也就是字符串数组,内部的数组的是动态开辟的,需要释放,但是这个析构函数是自动调用的。
2.2.3string的赋值重载
string类的赋值重载有三个,用的最多的还是前面两个。
int main() { string s1("hello c++"); string s2 = s1; string s3 = "hello c++"; cout << s2 << endl; cout << s3 << endl; return 0; }
2.2.4 string类对象的容量操作
2.2.4.1size和length
string类的size和length接口是完全一样的,只是由于STL的发展历史原因,后面才出现的size。虽说length出现的早,但是实际上size用的更多,都不包含/0。
2.2.4.2operator[]
那么我们怎么遍历一个string类的对象呢?使用[]是比较方便的,也更加容易理解,因为原始数组就是用的[]遍历的,[]就是operator[],运算符重载。
int main() { string s1 = "hello world"; for (int i = 0; i < s1.size(); i++) { cout << s1[i] << " "; } cout << endl; return 0; }
[]不仅可以读,也可以写,因为返回值是起始字符的引用。
int main() { string s1 = "hello world"; for (int i = 0; i < s1.size(); i++) { cout << s1[i]; } cout << endl; s1[0] = 'z'; cout << s1 << endl; return 0; }
[]在字符串的遍历这方面也挺方便的,用起来跟数组的下标一样。
2.2.4.3c++的swap
c++的库里面有一个swap函数,用起来非常的方便,库里面的swap是一个函数模板,所以可以支持各种数据类型。
2.2.4.4迭代器
c++里面还有一个东西可以支持大部分数据类型的的遍历,那就是迭代器(iterator),迭代器不仅可以遍历,还可以修改,迭代器是主流的访问容器的一种方式。下标和[]适用于物理空间上是连续的情况,链式结构,树形结构,哈希表等就只能用迭代器来遍历。
注意:const_iterator是const迭代器,它的目的是使迭代器指向的内容不能被修改,而不是迭代器本身不能被修改。
2.2.4.5rbegin
如果我们想倒着访问string类的对象,可以使用反向迭代器reverse_iterator,rbegin指向最后一个字符,rend就是第一个字符,it++就是向前遍历。
2.2.4.6reserve
reserve就是保留的意思,可以给string预留空间,也就是开空间,在我们知道需要多少空间时,可以用reserve提前开好空间,reserve只影响容量,不会影响数据,当然各个编译器的机制不一样。
2.2.4.7capacity
capacity就是容量,代表的是实际能存放多少个字符,而不是实际空间有多大,因为最后还有\0,\0不算是有效字符,是个标识符,实际空间比capacity大一,因为要留个空间存放\0。
int main() { string s1 = "hello zxf"; string::reverse_iterator it = s1.rbegin(); while (it != s1.rend()) { cout << *it; it++; } cout << endl; s1.reserve(30); cout << s1 << endl; cout << s1.capacity() << endl; return 0; }
2.2.4.8resize
大家再来看一下resize这个接口,resize既影响容量,也会影响数据,resize之后的容量肯定要比resize的数据要大,保证空间足够,size则为resize的大小,resize如果比之前的容量大,则会发生扩容,那么resize之后的数据既然是100了,那么当我们打印出来的时候,为什么什么都看不见呢?因为后面的数据全部都是\0。如果不想让后面是\0,就可以使用resize的一个重载,这个重载的第二个参数是一个字符。意思就是如果显示传了这个字符,那么后面插入的字符就是该字符,如果没有传的话,则是\0这个空字符。
在vs编译器上,如果resize的数据在size和capacity之间的话,那么size会发生变化,capacity不会变。
在vs编译器上,如果resize的数据小于size,那么size会减小,并且数据会删除,capacity不会变。
总结:
1.resize数据>capacity,扩容+尾插
2.size
3.resize数据
2.2.4.9push_back
push_back这个函数一次只能尾插一个字符,效率太低了,因此我们可以使用append。
2.2.4.10append
append函数有许多个重载,使用的方法也很简单,就不一一介绍了。
2.2.4.11operator+=
虽然append实现了这么多重载,但是有一个接口更加好用,就是运算符+=的重载。+=不仅更加的方便,并且代码的可读性也变强了。
2.2.4.12insert
insert这个接口只要第一个和第三个重载用的最多,在某个位置插入字符串或者string类的对象。
2.2.4.13erase
erase用法也很简单,不做过多说明。
2.2.4.14assign
assign相当于赋值,也有许多个重载。
2.2.4.15replace
replace就是替换的意思,虽然看起来很好用,但是成本比较高,不太推荐使用。
2.2.4.16find
find就是查找某个字符,可以从任意位置开始查找,返回的是这个字符的下标,不给开始查找的位置则默认为0,如果找不到的话返回值是整型的最大值.
2.2.4.17copy
copy就是拷贝string类对象的一部分到一个数组里面去,下面这段代码就是从拷贝下标为4的位置开始拷贝,拷贝长度为6的字符。
2.2.4.18find_first_of
find_first_of就是在string类的对象里面找到需要找的字符,并且返回下标,注意寻找的可以是多个。
2.2.4.19find_last_of
find_last_of就是从后往前找,用法和find_first_of是一样的。
2.2.4.20substr
substr就是从pos位置开始读出长度为len的字符串,返回的是string类。
今天的分享到这里就结束了,感谢大家的阅读!