目录
一、string的定义和初始化
string的底层大概是这样子的一个框架
class string
{
private:
char* _ptr;
char _buf[16];
size_t _size;
size_t _capacity;
};
当存储的字符串大小比较小时,就储存在buf中,如果比较大就动态开辟内存
string::npos的值是整型的最大值
string s1 默认初始化,s1是一个空串
string s2(s1)s2是s1的一个副本
string s2 = s1 s2是s1的一个副本
string s3(“value”)
string s3 = “value”(本质是一个隐式类型转换)
string s4(n, ‘a’) 初始化为由n个a组成的字符串
string s5 (s3, 0, 3) 从s3【0】开始向后取三个字符初始化
二.capacity大类的接口
1.str.size() 返回字符串大小(同str.length())
2.str.capacity() 返回字符串的容量,即总空间大小
3.str.empty()检测字符串是否为空串,是的话返回true,否的话返回false
4.str.clear()清除有效字符
5.str.resize()(缩小size时size改变capacity不变,扩大size至大于capacity时,capacity,size都会改变)作用有扩容和初始化
str.resize(100)
str.resize(100,'a')
str.resize(1)
如果空间扩大默认状态下多出来的部分会补充‘\0’,但是也可以自行改变补充的值
也可以缩小size,但是不会缩容
6.str.reserve()(改变capacity,不会改变size)
str.reserve(100)
如果我们知道要开多少空间,我们可以提前开好空间,减少扩容,扩容所产生的消耗太大了
由于一些对齐之类的原因,有可能开的不是100,但是一定不会比100小
三、Modifiers大类
1.+=
运算符重载,主要使用这种形式增加
s1 += 'a';
s1 += 'hello';
2.push_back 在末尾插入一个字符
str.push_back('a')
3.append 在末尾增加一个字符串
str.append('hello')
4.insert
str.insert(0,"hello");
str.insert(0, " ");
str.insert(0, 1 ,' ');//与上面效果相同,但是插入字符要写明插入几个
str.insert(str.begin() + n, ' ');
但是不推荐经常使用insert,要移动数据消耗很大
5.erase
str.erase(5, 1);//从第五个位置开始删除1个数据
str.erase(str.begin() + 5);//删除迭代器所指位置
如果删除的数据太短,那么删除到末尾,或者使用缺省值,默认使用npos
str.erase(5,1000);
str.erase(5);
6.replace
str.replace(5,"abc");//第五个字符替换为abc
但是不推荐使用,因为空间小了要扩容,还要挪动数据,消耗比较大
7.swap
str1.swap (str2);
相对于模板中的swap,这个的效率更高,只需要把指针交换即可,而模板中的swap则需要创建临时变量并且进行深拷贝
四、迭代器
1.普通迭代器
str.begin()
.str.end()
可以理解成一个像指针的东西,str.begin()理解成取str[0]的地址,str.end()则是取字符串最后一位后面的那个位置的地址
string s1("hello world");
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";
++it;
}
范围for的底层就是迭代器
for (auto ch : s1)
{
cout << ch << " ";
}
2.reverse反向迭代器
str.rebegin()
str.rend()
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit << " ";
++rit;
}
3.const 迭代器,只能读不能改
string::const_iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
4.const 反向迭代器
string::const_reverse_iterator it = s.rbegin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
(这个类里面还有cbegin(),cend(),crebegin(),crend())来区分普通和const修饰的类型,但是使用不广泛。
五、access大类
1.[], []的运算符重载也包含了普通版本和const版本的返回值
2.str.at()
的效果与返回值与[]一样
str.at(10)
但是两者区别是,当[]越界,程序会报错和终止
at则是通过抛异常来提示,一般来说at用得很少。
3.str.front()
4.str.back()
用于获取第一个和最后一个元素,但是也用的不多
六、operations
1.find
str.find('.');
str.find("haystack");
str.find(str2);
//第二个参数是pos,缺省是默认从下标为0处寻找
找到时返回对应下标,找不到返回npos
2.rfind
str.rfind('.');
倒着找回来,可以从某个位置找回来,默认是从最后
3.c_str
str.c_str();
返回字符串的地址
其它的指针会按指针打印,但是const char * 会按照字符串打印
string a = "hello";
cout << a << endl;
cout << a.c_str() << endl;//打印字符串
cout << (void*)a.c_str() << endl;//打印地址
但是如果是使用流插入打印,那么打印出来的内容是按照size打印,如果使用c_str(),即使用const char *打印,那么会受到'\0'的影响
(c_str的作用主要是与c语言兼容)
5.substr
string str2 = str.substr (3,5);//从某个位置向后找几个位置,返回string
6.find_first_of
效果类似find,寻找给出的字符串或者string里面的字符,默认从下标为0处开始寻找
str.find_first_of("haystack");
str.find_first_of(str2);
7.find_last_of
类似find_first_of,可以理解为从后往前找