1、STL简介
1.1、什么是STL
是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
1.2、STL六大组件
1、容器:string ; vector ; list ;deque ; map ; set ; multimap ; mutilset
2、迭代器: iterator ; const_iterator ; reverse_iterator ;const_reverse_iterator
3、仿函数: greater; less....
4、算法: find; swap; reverse ;sort ; merge ;
5、空间配置器: allocator
6、配接器: stack ; queue ; priority_queue
2、标准库中的string
2.1、string类的常用接口说明
1、string类对象的常见构造
string():构造空的string类对象,即空字符串
string(const char*s) :C-string来构造string类对象,常量字符串进行初始化。
string s1("hello");
string(size_t n,char c) : string类对象中包含n个字符c
string s2(10,'*');
string(const string&s): 拷贝构造函数
string s3(s2);
2、string类对象的容量操作
size():返回字符串有效字符长度
length():返回字符串有效字符长度
capacity():返回空间总大小
empty():检测字符串释放为空串,是返回true,否则返回false
caear():清空有效字符
reserver():为字符串预留空间
resize():将有效字符的个数改为n个,多出的空间用字符c填充
3、访问及遍历操作
operator[ ]:返回pos位置的字符, const string 类对象调用
可以一个一个打印字符,可以遍历字符串。可以像数组一样去使用
begin+ end:获取一个字符的迭代器+end获取最后一个字符的下一个位置的迭代器
rbegin + rend:同上
范围for:C++11支持更简洁的范围for的新遍历方式
char s3 = "hello world";
s3[1];---->它的底层是-----(s3是数组名,数组名是首元素地址)。*(s3+1)
s1[1];----->它的底层是-----s1.operator[](1);
4、string类对象的修改操作
push back:在字符串后尾插字符c (一个字符)
append:在字符串之后追加一个字符串 (一个字符串)
operator+=:在字符串后追加字符串str (一个字符串) (自己会扩容)
c str:返回c格式字符出
find+npos:从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind:从字符串pos的位置开始往前找字符c,返回该字符·在字符串中的位置
substr:在str中从pos位置开始,截取n个字符,然后将其返回
5、str类的非成员函数
operator+:尽力少用,因为传值返回,导致深拷贝效率低
operator>>:数入运算符重载
operator<<:输出运算符重载
getline:获取一行字符串
relation operators:大小比较
6、增删改查
void reserve(size_t n) //reserve开空间不只是给push_back和append使用,外面的开空间也可以使用,因此需要对n进行判断
{
if(n > _capacity)
{
char* tmp = new char[ n +1];
strcpy(tmp,_str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void push_back(char ch)
{
if(_size == capacity)
{
//2倍扩容
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[size] = ch;
++size;
_str[_size] = '\0';
}
void append(const char* str)
{
size_t len = strlen(str);
if(_size + len > _capacity)
{
//至少扩容到size+len
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
6、迭代器(先进行简单了解)
string::iterator it = s1.begin(); //begin指向字符串的第一个字符
while(it != s1.end()) //end指向字符串最后一个字符的下一个字符
{
cout << *it <<" "; //begin返回值给it *it就是数据
++it; //就是让it往后移动 等于end就结束了
}
cout<<endl;
//还有一个遍历字符串的方式就是使用范围for 也被称作“语法糖”
for(auto ch : s1) //将s1给ch 然后自动推导类型,自动判断结束 //注意:这样写只能读不能进行写,这只是单纯的赋值
{
cout<< ch << " "; // “读”
}
cout<<endl;
for(auto &ch : s1)//只有加&才可以进行写,因为这相当于修改的是s1的别名
{
ch++;
cout<< ch << " ";
}
//其实范围for的底层就是迭代器
//还有反向迭代器
string s1("hello world");
string::reverse_iterator rit = s1.rbegin(); //rbegin在字符串最后一个字符的下一个字符
while(rit != s1.rend()) //rend在第一个字符
{
cout << *rit <<" ";
++rit;
}
cout<<endl;
其实,iterator是一个像指针一样的类型,有可能是指针,有可能不是指针。
//任何容器都支持迭代器,并且用法是类似的
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
cout << *vit << " ";
++vit;
}
cout << endl;
下标+[]其实并不是主流的方式,因为树和链表就不能使用。但是数组、链表、树 都可以使用迭代器。(iterator提供的是一种统一的方式访问和修改容器的数据,算法就可以通过迭代器去处理容器中的数据)
6.1、迭代器的使用(先简单了解)
1、std::reverse ---->逆置
//接上面的代码
reverse(v.begin(),v.end());
for(auto e : v)
{
cout << e << " ";
}
cout <<endl;
3、string类的模拟实现
class String
{
public:
String(const char* str = "")
{
if(nullptr == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str,str);
}
String(const String& s)
:_str(nullptr)
{
String strTmp(s._str);
swap(_str,strTmp._str);
}
String& operator=(String s)
{
swap(_str,s._str);
return *this;
}
~String()
{
if(_str)
{
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
};
4、扩展阅读
5、补充
1、当字符串中包含空格时,如果使用流提取运算符,会默认空格作为分隔符来提取字符串。如果使用>>来提取字符串,只会得到第一个空格之前的字符串,而剩余部分会被留在输入流中。这可能导致后续的提取操作无法获取到预期的结果。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str; cout << "Enter a string with spaces: ";
cin >> str;
cout << "You entered: " << str << endl;
return 0;
}
例如上面的代码,如果输入hello world ,str只会读到hello。而 "World" 部分会留在输入流中,而不会被赋值给
str。
为了解决这个问题,可以考虑使用
getline
函数来读取一整行,而不是使用>>
操作符#include <iostream>
#include <string>using namespace std;
int main() {
string str;
cout << "Enter a string with spaces: ";
getline(cin, str);
cout << "You entered: " << str << endl;
return 0;
}getline
函数会读取整行,包括其中的空格,而不会将空格视为分隔符。2、string初始化的时候不能直接将str赋值给_str,必须要开空间--------------------
_str(new char[strlen(str)+1])