STL
string容器
C++风格的字符串,本质上是个类
与char*
的区别:
char*
是个指针string
是个类,内部封装了char*
,管理字符串,算是一个char*
型的容器
一些常用的方法
构造函数原型:
- string(); //创建空字符串
- string(const char* s); //初始化s,相当于类型转换
- string(const string& str); //初始化另一个字符串
- string(int n, char ch); //使用 n 个 字符ch 初始化
实例:
const char* ch = "hello";
string s1(ch); //把c_string 转换成string => 得到 s1
string s2(10,"a"); // string s2 = "aaaaaaaaaa";
赋值函数原型:
- string& operator=(const char* s); // 把char*的字符串赋给 string
- string& operator=(const string &s); //...
- string& operator=(char c); //字符赋值给字符串
- string& assign(const char*s); //...
- string& assign(const char *s, int n); //把字符串前 n 个字符赋值给当前字符串
- string& assign(const string &s); //...
- string& assign(int n, char c); // ...
实例:
string str1 = "hello world";
str2 = str1;
str3 = 'a'; // 'a'是 字符【单引号】
string s;
s.assign(str1)
string stra; //要先声明
stra.assign(10,'a'); //stra = "aaaaaaaaaa"; [只能是但引号,char类型]
字符串拼接:
重载了 += 操作符,以及append()函数
- string& operator+=(const char* s);
- string& operator+=(const char c);
- string& operator+=(const string& str);
- string& append(const char *s); 把字符串接到当前字符串后面
- string& append(const char *s, int n); //把字符串 s 前 n 个字符接到当前字符串后面
- string& append(const string &s); //...
- string& append(const string &s, int pos, int n); //字符串 s 中从pos开始的n个字符...
实例:
string s1 = "My ";
s1 += "name is Koi"; //s1 = "My name is Koi"
string s2 = "I";
s2.append(" love");
s2.append(" game abcd",5); //s2 = "I love game";
查找和替换:
find()、rfind()、replace()
find()查找是从左往右,rfind()从右往左
find()找到后返回查找的第一个字符的位置,没找到返回 -1
replace()替换时,要指定从哪个位置开始,多少个字符、替换成什么样的字符串
- int find(const string& str, int pos = 0) const; //...
- int find(const char *s, int pos = 0) const; //...
- int find(const char *s, int pos = 0,int n) const; //从 pos 开始查找 s的前 n 个字符的第一次
- int find(const char ch,int pos); //...查找字符 ch
-- rfind()同上---
- string& replace(int pos, int n, const string& str); //...
- string& replace(int pos, int n, const char *s); //...
字符串比较:
compare(),返回数字 = 返回 0,> 返回 1, < 返回 -1
- int compare(const string &s);
- int compare(const char *s);
字符串的存取:
- char& operator[](int n);
- char& at(int n);
实例:
string str = "hello world";
//遍历
for (int i = 0; i < str.size();i++) {
cout << str.at(i) << " ";
}
//修改
str[0] = 'x';
str.at(0) = 'y';
字符串的插入与删除:
insert 和 erase【删除】
- string& insert(int pos, const char* s); //...
- string& erase(int pos, int n); // 删除 pos开始的 n 个字符
实例:
string s = "hello";
s.erase(1,3); //s = "ho";
子串:
substr函数
- string substr(int pos, int n); //从 pos 开始的 n 个字符
实例:
string str = "abcdefg";
string sub = str.substr(1,3); // sub = "bcd";
vector容器
也称为单端数组
vector可以动态扩展
动态扩展并不是在原空间之后接新空间,而是找更大的内存空间,然后将元数据拷贝到新空间,释放原空间。
vector常用的方法
创建vector容器
- vector<typename> v; //采用模板实现类实现,默认构造函数
- vector(v.begin(), v.end()); //将 v[begin(), end()]区间的元素拷贝给本身
- vector(n, elem); //将 n 个elem拷贝给本身
- vector(const vector &vec); //拷贝构造函数
实例:
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i); //在末尾追加
} // v1 = {0,1,2,3,4,5,6,7,8,9}
vector<int> v2(v1.begin(),v1.end()); //v2 = {0,1,2,3,4,5,6,7,8,9}
vector<int> v3(5,100); // v3 = {100,100,100,100,100}
vector<int> v4(v3); // v4 = {100,100,100,100,100}
vector赋值操作
- vector& operator=(const vector &vec); //重载运算符
- assign(begin, end); //将区间[begin, end)中的数据 ...
- assign(n, elem); //将 n 个 elem拷贝赋值给本身
实例:
vector<int> v(3,100); // v = {100,100,100}
vector<int> v1 = v; //v = {100,100,100}
vector<int> v2;
v2.assign(v1.begin(),v1.end());
vector<int> v3; //要先声明
v3.assign(2,5); // v3 = {5, 5}
创建vector容器
- empty();
- capacity(); //容器的容量
- size(); // 容器中的元素个数 【 个数 <= 容量 】
- resize(int num); // 重新制定容器的长度为num,如果变长就用默认值填充,如果变短,就删除
- resize(int num, elem); //以 elem填充
vector 插入和删除
- push_back(elem); //尾部插入元素 elem
- pop_back(); //删除最后一个元素
- insert(const_iterator pos, elem); // 迭代器指向位置 pos 插入 elem
- insert(consta-iterator pos, int n, typename elem); //迭代器指定位置pos插入n个elem
- erase(const_iterator pos); //删除迭代器指向的元素
- erase(const_iterator start, const_iterator end); // ...
- clear(); //清空容器
实例:
vector<int> v{1,2,3};
for(int i = 4; i < 10; i++) {
v.push_back(i); //v = {1,2,3,4,5,6,7,8,9}
}
// pop 删除
v.pop_back(); // v = {1,2,3,4,5,6,7,8}
//插入 insert
v.insert(v.begin(),100); //v = {100,1,2,3,4,5,6,7,8}
v.insert(v.begin(),2,100); // v = {100,100,100,1,2,3,4,5,6,7,8}
//删除
v.erase(v.begin()); // v = {100,100,1,2,3,4,5,6,7,8}
v.erase(v.begin(),v.begin()+2); //[ , )删除了前面两个
//v = {1,2,3,4,5,7,8}
//清空(两种方式)
v.erase(v.begin(),v.end());
v.clear();
vector 数据存取
- at(int index); //返回索引 index 所指的数据
- operator[](); //重载运算符
- front(); //返回第一个元素
- back(); //返回最后一个元素
实例:
vector<int> v1{0,1,2,3,4,5,6};
cout << "v1.at(2) = " << v1.at(2); //v1.at(2) = 2
cout << "v1[5] = " <<v1[5]; // v1[5] = 5
cout << "v1的第一个元素是:" << v1.front(); //v1的第一元素是0
cout << "v1的最后一个元素是:" << v1.back(); //v1的最后一个元素是6
vector 互换容器
- swap(vec); // 将vec与当前的vector元素交换
实例:
vector<int> v1{1,3,5};
vector<int> v2{2,4,6,8};
v1.swap(v2);
vector容器在使用时没有指定其容量,有系统自动分配,很方便,但造成了内存浪费,使用 swap()方法可以释放掉多余的内存。
实例:
void test02() {
vector<int> v;
for (int i = 0; i < 100000; ++i)
{
v.push_back(i);
}
cout << "容量:" << v.capacity() << endl;
cout << "大小:" << v.size() << endl;
v.resize(5);
// v.clear();
cout << "容量:" << v.capacity() << endl;
cout << "大小:" << v.size() << endl;
// printvector(v);
vector<int> (v).swap(v);
cout << "容量:" << v.capacity() << endl;
cout << "大小:" << v.size() << endl;
}
// c++ 11中可以使用方法shrink_to_fit()得到同样的效果。
由运行结果可以看到,在执行vector<int> (v).swap(v);
后就释放了多余的空间。
原因呢?
这句代码的作用是创建了一个新的匿名函数,将匿名函数与原函数做交换,交换后的容器的大小尽可能的接近容量或者相等。而匿名函数在发挥作用后就被释放了内存。
实际上,swap()
交换的是两个容器的指针,而并不是其迭代器,如果在swap()
之前就定义了迭代器,则交换后,虽然容器名的指向已经变了,但迭代器还是指向原内存空间,此时再对迭代器解引用将会得到错误的值。
vector<int>v1 = { 1,2,3 };
vector<int>::const_iterator it1 = v1.begin();
vector<int>v2 = { 4,5,6 };
vector<int>::const_iterator it2 = v2.begin();
v1.swap(v2);
//要更新指向
//it1 = v1.begin();
//it2 = v2.begin(); //如果没有这个会产生错误的结果
cout << "*it1=" << *it1 << endl;
cout << "*it2=" << *it2 << endl;
vector预留空间
减少vector在动态扩展容量是的扩展次数
- reverse(int len); //容器预留len个元素长度,预留位置不初始化,不可访问。
实例:
vector<int> v;
v.reserve(100); //此时的capacity = 100;size = 0;
deque容器
与vector的区别
- vector的头部插入效率低
- deque的头部插入删除速度比vector快
- vector访问元素的速度更快。
deque构造函数
- deque<typename> deqT;
- deque(d.begin(),d.end()); //[begin, end);
- deque(n, elem); // n 个 elem
- deque(const deque &deq); // 拷贝构造函数