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); // 拷贝构造函数
Last modification:February 10, 2023
请我喝瓶冰阔落吧