STL之string容器
为什么要学习string类
在c语言中,字符串以"\0"结尾的一些字符的集合,并且提供了一系列的str函数,但有时候可能会越界访问,且库函数是与字符串分离的,不太符合OOP的思想,为了方便管理,c++封装了一个类
string类的常见接口
构造函数:
重点学习:
第一个构造空的string类对象(空字符串):string s1;注意不要加()这样可能会误以为s1是函数
第二个拷贝构造函数,可以看到这里加了&符合之前讲的避免死循环一直拷贝构造
第四个string s1("hello"); //传一个常量字符串
其余可以了解
一些简单的容量操作
size():返回字符串的有效长度(一般用这个,length比较早期,size是与其他容器统一)
length():返回字符串的有效长度
capacity():返回空间的总大小(capacity是表示开了多大的空间,size表示有效字符长度,两则意义不一样)
这是模拟实现的string,可以看出size和capacity两则意义不同
empty():检测字符串是否为空串,是返回true,否返回false
clear():清空字符串,只是把标记位size变为0,capacity不变
reserve():为字符串预留多大的空间(一般会以1.5倍或者2倍增容,但有增容代价,如果你知道你的空间多大,可以一次性开好,例如reserve(100);如果你的参数小于原来的,则不会改变容量)
resize():将有效字符的个数改成多少个,多出的空间用字符c填充
注意:当n<字符串长度时,这里的resize不是把多余的删除,而是把标记位size改变,下一次插入就会覆盖从而达到删除的效果
总结:resize是改变size(有效字符/标记位),reverse是改变capacity(容量)
clear不改变底层空间的大小
operator=
string类对象的修改操作
append():在字符串后面追加字符串(可以追加字符cplusplus有详细的函数调用方法)
push_back():在字符串后面追加字符c(只能追加字符c)
pop_back():尾删一个字符c
operator+=():更推荐使用这个去代替append和push_back,尾插什么都很方便
例如s1:hello s2:world s1+=s2 也就是相当于调s1.operator=(s2);
s1:helloworld s2:world
insert():在任意位置插入,pos表示任意一个位置,iterator是迭代器后面学
erase():在任意位置删除,pos表示任意一个位置,iterator是迭代器后面学
String operations(字符串操作)
c_str():返回c格式的字符串 (在string类中是以size表示有效大小,c风格是以\0表示结束,返回c格式的字符串是在末尾加\0,而string在处理字符串是没有\0结尾表示结束,而是用size)
以下常用来分隔字符串:
find():从pos个位置开始往后找(第三个函数是表示找s中的前几个字符,例如s.find(“hello“,0,3),那就会在s这个string类对象中找hel)
rfind():从某个位置开始往前找 (注意这里的npos为-1,但类型是size_t,也就是无符号的最大,也就是任何大于或等于字符串长度的都表示以搜索整个字符串)
注意:find和rfind的返回值,成功找到是返回pos那个位置,失败返回npos(-1);
substr():在str中从pos位置开始,截取n个字符,然后将其返回
总结 :结合find和rfind和substr就可以分隔字符串;
string类非成员函数
少用operator+因为传值返回,导致深拷贝效率低
重点关注relational operators(大小比较)
operator>><<:可以直接输出一个string类
getline():获取一行字符串
swap():交换两个字符串类最好用这个,这个就相当于只是交换指针等内部数据结构,效率O(1)而 <algorithm>
标准库中也实现了一个通用的swap函数,这个会去调拷贝构造函数和赋值函数创建一个临时对象来完成,效率是O(n)
operator[]遍历
两个版本一个是const修饰的,一个是非const修饰的
用这个可以下标遍历
迭代器遍历
这里先简单的理解迭代器为指针(后面学到更多的容器时会有更多的理解)
string::iterator it=s.begin();
while(it!=end())
{cout<<*it;++it;
}
cout<<endl;
begin():获取第一个字符的迭代器
end():获取最后一个字符下一个位置的迭代器(这里没有进行*it操作所以[size]没有解引用就不会有危险)
rbegin()+rend():与begin和end相反,这样就可以实现反向遍历
//reverse_iteratorstring s1("hello world");string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend())
{cout << *rit << " ";++rit;
}
注意:需要使用reverse_iterator反向迭代器
范围for遍历
范围for本质就是迭代器遍历,只要你的类支持迭代器遍历就支持范围for,编译器会在处理时把范围for变成迭代器遍历
void test5()
{string s1("hello world");for (auto e : s1){e = e + 1;cout << e;}cout << endl;for (auto e : s1){cout << e;}cout << endl;
}
这里由于你的auto没加引用&,e不是别名,没有改s1的helloworld
简单模拟实现string类
我已经把代码上传gitee:June: 这里包含我的c++和Linux及数据结构https://gitee.com/taifanshu/day2.git