C++ 提高篇 2 之 STL 及 string 容器

STL 初识

STL 基本概念

  1. STL 标准模板库
  2. STL 从广义上分为:容器、算法和迭代器
  3. 容器和算法之间通过迭代器进行无缝连接
  4. STL 几乎所有的代码都采用了模板类或者模板函数

STL 六大组件

》》STL 大体上分为六大组件,分别是容器、算法、迭代器、仿函数、适配器和空间配置器

  1. 容器:各种数据结构,如 vector、list、deque、set、map 等,用来存放数据
  2. 算法:各种常用的算法,如 sort、find、copy、for_each 等
  3. 迭代器:扮演了容器和算法之间的胶合剂
  4. 仿函数:行为类似函数,可作为算法的某种策略
  5. 适配器:一种用来修饰容器、仿函数或者迭代器接口的东西
  6. 空间配置器:负责空间的配置与管理

STL 中容器、算法和迭代器

》》容器

  1. STL 容器就是运用一些最广泛的数据类型实现出现
  2. 常用的数据结构:数组、链表、树、栈、队列、集合、映射表等
  3. 可以分为序列式容器和关联式容器二类
  4. 序列式容器强调值的排序,其中的元素都有固定的位置
  5. 关联式容器属于二叉树结构,其中的元素没有固定的位置关系

》》算法

  1. 有限的步骤解决逻辑或数学上的问题,称为算法
  2. 算法分为质变算法和非质变算法二类
  3. 质变算法指运算过程会改变区间元素内容,如拷贝、替换和删除等
  4. 非质变算法指运算过程不会改变区间元素内容,如查找、计数、遍历和寻找极值等

》》迭代器

  1. 提供一种方法,使之能够依序访问容器中的每个元素,而又无需暴露容器内部的表示方式
  2. 每个容器都有属于自己的迭代器,迭代器的使用非常类似于指针
  3. 迭代器可以分为输入、输出、前向、双向、随机迭代器

vector 存放内置数据类型

容器:vector(所需头文件 #include <vector>

算法:for_each(所需头文件 #include <algorithm>

迭代器:vector<int>::iterator

#include <iostream>
using namespace std;
#include <vector> // 容器
#include <algorithm> // 算法

void Print(int value) {
	cout << value << " ";
}

int main() {

	// 1. 创建一个 vector 容器,数组
	vector<int> v;

	// 2. 向容器中插入数据
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	
	// 3. 通过迭代器访问容器中的数据
	vector<int>::iterator itBegin = v.begin(); // 起始迭代器,指向容器中的第一个元素
	vector<int>::iterator itEnd = v.end(); // 结束迭代器,指向容器中最后一个元素的下一个位置
	// itBegin 和 itEnd 都属于指针
	// 3.1 第一种遍历方法
	while (itBegin != itEnd) {
		cout << *itBegin << " "; // 10 20 30
		itBegin++;
	}
	cout << endl;
	// 3.2 第二种遍历方法
	for (vector<int>::iterator it = v.begin(); it < v.end(); it++) {
		cout << *it << " "; // 10 20 30
	}
	cout << endl;
	// 3.3 第三种遍历方法 -- 利用 STL 提供遍历的算法
	for_each(v.begin(), v.end(), Print); // 10 20 30
	cout << endl;

	system("pause");
	return 0;
}

解释:如下程序创建了一个容器数组 v;并利用 push_back 函数插入了三条 int 类型的数据;随后通过迭代器访问数组中的元素:访问方法如下举了三个例子,第一种和第二种类似,用二个变量接收容器 v 的起始地址和末尾后(末尾后一个)地址,用遍历的方式访问元素,第三种则是通过算法 for_each,其中传入了三个参数,第一个和第二个参数分别是起始地址和末尾后地址,第三个参数传递了一个函数名,函数形参为数组中的元素

vector 存放自定义数据类型

自定义 Person 数据类型,其中包含二个成员属性(Name_ 和 Age_)

第一种:vector 容器数组中存放 Person 对象

#include <iostream>
using namespace std;
#include <string>
#include <vector> // 容器

// 自定义数据类型
class Person {
public:
	Person(string name, int age) {
		Name_ = name;
		Age_ = age;
	}
public:
	string Name_;
	int Age_;
};

int main() {

	// 1. 创建容器对象
	vector<Person> v;

	// 2. 创建数据并插入数据
	Person p1("A", 1);
	Person p2("B", 2);
	Person p3("C", 3);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);

	// 3. 输出数组中的数据
	for (vector<Person>::iterator it = v.begin(); it < v.end(); it++)
	{
		cout << "Name:" << (*it).Name_ << " Age:" << (*it).Age_ << endl;
	}
	// outputs:Name:A Age:1
	//		   Name:B Age:2
	//		   Name:C Age:3

	system("pause");
	return 0;
}

第二种:vector 容器数组中存放 Person 对象地址

#include <iostream>
using namespace std;
#include <string>
#include <vector> // 容器

// 自定义数据类型
class Person {
public:
	Person(string name, int age) {
		Name_ = name;
		Age_ = age;
	}
public:
	string Name_;
	int Age_;
};

int main() {

	// 1. 创建容器对象
	vector<Person*> v;

	// 2. 创建数据并插入数据地址
	Person p1("A", 1);
	Person p2("B", 2);
	Person p3("C", 3);
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);

	// 3. 输出数组中的数据 -- 此时 *it 变为一个指针
	for (vector<Person*>::iterator it = v.begin(); it < v.end(); it++)
	{
		cout << "Name:" << (*it)->Name_ << " Age:" << (*it)->Age_ << endl;
	}
	// outputs:Name:A Age:1
	//		   Name:B Age:2
	//		   Name:C Age:3

	system("pause");
	return 0;
}

vector 容器嵌套容器

#include <iostream>
using namespace std;
#include <string>
#include <vector> // 容器

// 自定义数据类型
class Person {
public:
	Person(string name, int age) {
		Name_ = name;
		Age_ = age;
	}
public:
	string Name_;
	int Age_;
};

int main() {

	// 1. 创建容器对象
	vector<vector<int>> v;

	// 2. 创建数据对象并为之插入数据 -- 次容器 
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	for (int i = 0; i < 3; i++) {
		v1.push_back(i + 1);
		v2.push_back(i + 2);
		v3.push_back(i + 3);
	}
	// 3. 往主容器中插入数据
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);

	// 4. 遍历主容器对象
	for (vector<vector<int>>::iterator it = v.begin(); it < v.end(); it++) {
		for (vector<int>::iterator iit = (*it).begin(); iit < (*it).end(); iit++) {
			cout << (*iit) << " ";
		}
		cout << endl;
	}
	// outputs:1 2 3
	//         2 3 4
	//		   3 4 5
	

	system("pause");
	return 0;
}

string 容器

string 基本概念

本质

string 是 C++ 风格的字符串,而 string 本质上是一个类

string 和 char * 的区别

  1. char * 是一个指针
  2. string 是一个类,类内部封装了 char *,是一个 char * 型的容器

特点

  1. string 类内部封装了很多成员方法,如查找、拷贝、删除、替换和插入等
  2. string 管理 char * 所分配的内存,不用担心复制越界和取值越界问题

string 构造函数

构造函数原型

  1. string(); // 创建一个空的字符串,如 string str;
  2. string(const char * s); // 使用字符串 s 初始化
  3. string(const string& s); // 使用一个 string 对象初始化另一个 string 对象
  4. string(int n, char c); // 使用 n 个字符 c 初始化
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 1. 默认构造
	string s1;
	cout << s1 << endl; // 空字符串

	// 2. 有参构造
	const char * str = "love"; // C 风格字符串
	string s2(str);
	cout << s2 << endl; // love

	// 3. 使用一个 string 对象初始化字符串
	string s3(s2);
	cout << s3 << endl; // love

	// 4. 使用 n(10) 个字符 c(g) 初始化
	string s4(10, 'g');
	cout << s4 << endl; // gggggggggg

	system("pause");
	return 0;
}

string 赋值操作

赋值的函数原型

  1. string& operator=(const char* s); // 字符串 s 赋值给当前的字符串
  2. string& operator=(const string &s); // 字符串对象 s 赋值给当前的字符串
  3. string& operator=(char c); // 字符赋值给当前的字符串
  4. string& assign(const char *s); // 字符串 s 赋值给当前的字符串
  5. string& assign(const char *s, int n); // 字符串 s 的前 n 个字符赋值给当前的字符串
  6. string& assign(const string &s); // 字符串对象 s 赋值给当前字符串
  7. string& assign(int n, char c); // 将 n 个字符 c 赋值给当前字符串
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 默认构造
	string s1; // 空字符串
	// 有参构造
	string s2("you");
	// 使用 5 个 r 初始化字符串
	string s3(5, 'r');

	// 等号赋值操作
	// 1. 字符串 "love" 赋值给字符串 s1
	s1 = "love";
	cout << s1 << endl; // love
	// 2. 字符串对象 s2 赋值给 s1
	s1 = s2;
	cout << s1 << endl; // you
	// 3. 字符对象 c 赋值给字符串 s1
	s1 = 'm';
	cout << s1 << endl; // m
	
	// assign 函数赋值操作
	// 1. 字符串 "his" 赋值给字符串 s1
	s1.assign("his");
	cout << s1 << endl; // his
	// 2. 字符串 "his" 前 n 个元素赋值给字符串 s1
	s1.assign("her", 2);
	cout << s1 << endl; // he
	// 3. 字符串 s3 赋值给字符串 s1
	s1.assign(s3);
	cout << s1 << endl; // rrrrr
	// 4. 将 n(5) 个字符 c(b) 赋值给字符串 s1
	s1.assign(5, 'b');
	cout << s1 << endl; // bbbbb

	system("pause");
	return 0;
}

string 字符串拼接

字符串拼接的函数原型(append 函数不可拼接字符)

  1. string& operator+=(const char * s); // 拼接字符串 s
  2. string& operator+=(const char c); // 拼接字符 c
  3. string& operator+=(const string & s); // 拼接字符对象 s
  4. string& append(const char *s); // 拼接字符串 s
  5. string& append(const char *s, int n); // 拼接字符串 s 的前 n 个字符
  6. string& append(const string &s); // 拼接字符串对象 s
  7. string& append(const string &s, int pos, int n); // 拼接从索引 pos 开始的 n 个字符
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 构造函数
	string s1; // 空字符串
	// 有参构造
	string s2("you"); 

	// 加等号拼接字符串
	// 1. 拼接字符串 s
	s1 += "i";
	cout << s1 << endl; // i
	// 2. 拼接字符 c
	s1 += 'l';
	cout << s1 << endl; // il
	// 3. 拼接字符串对象 s2
	s1 += s2;
	cout << s1 << endl; // ilyou
	
	// append 函数拼接字符串
	// 1. 拼接字符串 s
	s1.append("beat");
	cout << s1 << endl; // ilyoubeat
	// 2. 拼接字符串 s 的前 n 个字符
	s1.append("ful", 2);
	cout << s1 << endl; // ilyoubeatfu
	// 3. 拼接字符串对象 s2
	s1.append(s2);
	cout << s1 << endl; // ilyoubeatfuyou
	// 4. 拼接字符串从索引位置 2 开始的 2 个字符
	s1.append("abcdefg", 2, 2);
	cout << s1 << endl; // ilyoubeatfuyoucd
			
	system("pause");
	return 0;
}

string 查找和替换

字符串查找:查找指定字符串是否存在

  1. int find(const string& s, int pos = 0) const; // 从索引为 pos 往后查找字符串对象 s 第一次出现的位置
  2. int find(const char* s, int pos = 0) const; // 从索引为 pos 往后查找字符串 s 第一次出现的位置
  3. int find(const char* s, int pos, int n) const; // 从索引为 pos 往后查找字符串前 n 个字符第一次出现的位置
  4. int find(const char c, int pos = 0) const; // 从索引为 pos 往后查找字符 c 第一次出现的位置
  5. int rfind(const string& s, int pos = npos) const; // (逆序)从索引为 pos 往前查找字符串对象 s 第一次出现的位置
  6. int rfind(const char* s, int pos = npos) const; // (逆序)从索引为 pos 往前查找字符串 s 第一次出现的位置
  7. int rfind(const char* s, int pos, int n) const; // (逆序)从索引为 pos 往前查找字符串前 n 个字符第一次出现的位置
  8. int rfind(const char c, int pos = npos) const; // (逆序)从索引为 pos 往前查找字符 c 第一次出现的位置
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("iloveyoubabyyoukonw!");
	// 有参构造
	string s2("ou");
	// 初始化字符
	string s3;
	s3 = 'u';
	
	// 正序查找
	// 1. 从索引为 0 往后查找字符串对象 s2,返回第一次出现位置的索引
	cout << s1.find(s2) << endl; // 6 
	// 2. 从索引为 0 往后查找字符串 "ou",返回第一次出现位置的索引
	cout << s1.find("ou") << endl; // 6 
	// 3. 从索引为 0 往后查找字符串 "ou" 的前 1 个元素,返回第一次出现位置的索引
	cout << s1.find("ou", 0, 1) << endl; // 2
	// 4. 从索引为 0 往后查找字符 'v',返回第一次出现位置的索引
	cout << s1.find('v') << endl; // 3

	// 逆序查找
	// 1. (逆序)从索引为 20 往前查找字符串对象 s2,返回第一次出现位置的索引
	cout << s1.rfind(s2) << endl; // 13
	// 2. (逆序)从索引为 20 往前查找字符串 "ou",返回第一次出现位置的索引
	cout << s1.rfind("ou") << endl; // 13
	// 3. (逆序)从索引为 20 往前查找字符串 "ou" 的前 1 个元素,返回第一次出现位置的索引
	cout << s1.rfind("ou", 20, 1) << endl; // 16
	// 4. (逆序)从索引为 20 往前查找字符 'v',返回第一次出现位置的索引
	cout << s1.rfind('v') << endl; // 3


	system("pause");
	return 0;
}

字符串替换:在指定的位置替换字符串

  1. string& replace(int pos, int n, const string &s); // 从 pos 开始的 n 个字符替换为字符串对象 s
  2. string& replace(int pos, int n, const char* s); // 从 pos 开始的 n 个字符替换为字符串 s
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("loveyou");
	// 有参构造
	string s2("me");

	// 1. 替换字符串对象 s2
	s1.replace(4, 3, s2);
	cout << s1 << endl; // loveme
	
	// 2. 替换字符串
	s1.replace(4, 2, "him");
	cout << s1 << endl; // lovehim

	system("pause");
	return 0;
}

string 比较

函数原型

  1. int compare(const string &s) const; // 与字符串对象 s 比较
  2. int compare(const char *s) const; // 与字符串 s 比较

比较方式:根据字符的 ASCII 码;相等则返回 0;大于则返回 1;小于则返回 -1;

#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("loveyou");
	// 有参构造
	string s2("me");

	// 1. 与字符串对象比较
	cout << s1.compare(s2) << endl; // -1
	cout << s1.compare(s1) << endl; // 0

	// 2. 与字符串对比
	cout << s1.compare("loveyou") << endl; // 0
	cout << s1.compare("loveyoue") << endl; // -1
	cout << s1.compare("loveyo") << endl; // 1

	system("pause");
	return 0;
}

string 字符存取

string 中单个字符存取方式有二种

  1. char& operator[](int n); // 通过索引取字符
  2. char& at(int n); // 通过 at 方式取字符
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("loveyou");

	// 第一种方式
	for (int i = 0; i < s1.size(); i++) {
		cout << s1[i] << " "; // l o v e y o u
	}
	cout << endl;

	// 第二种方式
	for (int j = 0; j < s1.size(); j++) {
		cout << s1.at(j) << " "; // l o v e y o u
	}
	cout << endl;

	system("pause");
	return 0;
}

string 插入和删除

函数原型

  1. string& insert(int pos, const char* s); // 插入字符串 s
  2. string& insert(int pos, const string& s); // 插入字符串对象 s
  3. string& insert(int pos, int n, char c); // 在指定位置插入 n 个字符 c
  4. string& erase(int pos, int n); // 删除从 pos 开始的 n 个字符
#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("loveyou");
	string s2("his");

	// 1. 插入字符串
	s1.insert(0, "me");
	cout << s1 << endl; // meloveyou
	// 2. 插入字符串对象
	s1.insert(2, s2);
	cout << s1 << endl; // mehisloveyou
	// 3. 在指定位置插入 n 个字符
	s1.insert(0, 3, 'a');
	cout << s1 << endl; // aaamehisloveyou

	// 4. 删除从 pos 开始的 n 个字符
	s1.erase(0, 5);
	cout << s1 << endl; // hisloveyou

	system("pause");
	return 0;
}

string 子串

函数原型

string substr(int pos, int n) const; // 返回由 pos 开始的 n 个字符组成的字符串

#include <iostream>
using namespace std;
#include <string>

int main() {

	// 有参构造
	string s1("loveyou");
	// 构造函数
	string s2;

	s2 = s1.substr(0, 3);
	cout << s2 << endl; // lov
	s2 = s1.substr(2, 4);
	cout << s2 << endl; // veyo

	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是我来晚了!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值