文章目录
-
注意事项
-
一、vector(常用容器)(尾部插入删除、可以遍历)
-
二、deque(双端数组)(头端插入删除、尾部插入删除、可以遍历)
-
三、string(结构类似于vector)
-
-
1 string容器基本概念
-
2 string构造函数(类似vector)
-
3 字符串长度获取(length、size、strlen)
-
4 string赋值操作 (operator=、assign)
-
5 string字符串拼接(operator+= 重载、append)
-
6 string查找和替换(find、rfind、replace)
-
7 string字符串比较(compare)
-
8 string字符存取(operator[] 重载、at )
-
9 string插入和删除(insert、erase)
-
10 string子串获取(substr)
-
11 C++ 中 string和char* 的区别
-
12 string和int的相互转换
-
注意事项
//1. 在str1尾插一个'A'字符,参数必须是字符形式
str1.puch_back ('A');
//2. vector<string> 不能拷贝到 string
vector<string> v = {"aa"}
string a(v.begin(), v.end()); //报错,不能区间拷贝
一、vector(常用容器)(尾部插入删除、可以遍历)
1 vector基本概念(随机存储效率高,插入删除不行)
- vector数据结构和数组非常相似,也称为单端数组
(1)vector与普通数组区别:
- 不同之处在于数组是静态空间,而vector可以动态扩展
(2)动态扩展:
-
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
- vector容器的迭代器是支持随机访问的迭代器(例v.begin()可以一下跳好几个)
-
vector是在尾部插入删除
front(); 代表容器中第一个元素
back(); 代表最后一个元素
vector<int> (v.rend(), v.rbegin());//反向迭代器创建临时对象
2 vector构造函数(默认构造、区间拷贝、n元素拷贝、拷贝构造)
vector<int> v1; //采用类模板实现,默认构造函数
vector<int> v2(v1.begin(), v1.end()); //将区间中的元素拷贝给本身(前闭后开)
vector<int> v3(10, 100); //构造函数将10个100拷贝给本身。(拷贝)
vector<int> v4(v3); //拷贝构造函数。(拷贝)
vector<int> v(10); //初始化了10个0
vector<int> v(10,1); //初始化了10个1
3 vector赋值操作(operator=、assign)
v2 = v1; //重载等号操作
v = { 38, 3, 44, 5, 36, 15, 27, 26, 2 }; //和C语言数组一样
v3.assign(v1.begin(), v1.end()); //将[beg, end)区间中的数据拷贝赋值给本身。(前闭后开)
v4.assign(10, 100); //将10个100拷贝赋值给本身。
//resize 重新指定容器的长度(大小)
v1.resize(15);
//重新指定容器的长度为15,若容器变长,则以默认值0填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
v1.resize(20,10); 20个10
//重新指定容器的长度为20,若容器变长,则以10值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除
5 vector插入和删除(insert、erase、clear)(迭代器找位置)
//尾插 尾删
v1.push_back(20); //尾部插入元素20
v1.pop_back(); //删除最后一个元素
//insert 指定位置插入
v1.insert(v1.begin(), 100); //迭代器指定位置插入元素100
v1.insert(v1.begin(), 2, 1000); //迭代器指定位置插入2个元素1000
//erase 指定位置删除
v1.erase(v1.begin()); //删除迭代器指向的元素
v1.erase(v1.begin(), v1.end()); //删除迭代器从begin到end之间的元素 (提供区间)
//clear 清除所有元素
v1.clear(); //删除容器中所有元素
6 vector数据存取(at、operator[]、front、back)(下标找位置)
//at 函数获取
v1.at(i) //返回索引(下标)idx所指的数据
//operator[ ] 重载[ ]
v1[i] //返回索引(下标)idx所指的数据
//front back 两个接口
v1.front() //返回容器中第一个数据元素
v1.back() //返回容器中最后一个数据元素
-
除了用迭代器获取vector容器中元素,[ ]和at也可以
7 vector互换容器(swap)
- 实现两个容器内元素进行互换
//swap 互换函数
v1.swap(v2);
//swap可以使两个容器互换,可以达到实用的收缩内存效果
vector<int>(v).swap(v); //匿名对象
8 vector预留空间(reserve 预定)
//1.减少vector在动态扩展容量时的扩展次数
//2.预留位置不初始化,元素不可访问。
v.reserve(10000); //容器预留10000个元素长度(是空地,不是0初始化)
-
如果数据量较大,可以一开始利用reserve预留空间
二、deque(双端数组)(头端插入删除、尾部插入删除、可以遍历)
1 deque容器基本概念[dek]
- deque容器的迭代器也是支持随机访问的
(1)deque与vector区别:
-
vector对于头部的插入删除效率低,数据量越大,效率越低
-
deque相对而言,对头部的插入删除速度会比vector快
-
但vector访问元素时的速度会比deque快,这和两者内部实现有关
(2)deque内部工作原理: -
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据。中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
2 deque构造函数(默认、区间、n个元素、拷贝)
deque<int> d1; //默认构造形式
deque<int> d2(d1.begin(), d1.end()); //构造函数将[beg, end)区间中的元素拷贝给本身
deque<int> d3(10, 100); //构造函数将10个100拷贝给本身。
deque<int> d4 = d3; //拷贝构造函数
- deque容器和vector容器的构造方式几乎一致,灵活使用即可
3 deque赋值操作(operator=、assign)
//operator= 重载
d2 = d1; //重载等号操作符
//assign 赋值函数
d3.assign(d1.begin(), d1.end()); //将[beg, end)区间中的数据拷贝赋值给本身。
d4.assign(10, 100); //将10个100拷贝赋值给本身。
- deque赋值操作也与vector相同,需熟练掌握
4 deque大小操作(resize、size、emply)(无容量)
capacity // 因为deque没有容量概念,可以无限扩充。
d1.empty() //判断容器是否为空
d1.size() //返回容器中元素的个数
//resize 重新指定容器的长度(大小)
d1.resize(5);
//重新指定容器的长度为5,若容器变长,则以默认值0填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
d1.resize(15, 1); 15个1
//重新指定容器的长度为15,若容器变长,则以1值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
5 deque插入和删除(insert、erase、clear)
//两端插入、删除操作
d.push_back(10); //在容器尾插入一个数据 (尾插)
d.push_front(100); //在容器头部插入一个数据(头插)
d.pop_back(); //删除容器最后一个数据 (尾删)
d.pop_front(); //删除容器第一个数据 (头删)
//insert 指定位置插入
d.insert(d.begin(), 10); //在迭代器pos位置插入一个10的拷贝,返回新数据的位置。
d.insert(d.begin(), 2, 10); //在迭代器pos位置插入2个10数据,无返回值。
d.insert(d.begin(), d2.begin(), d2.end()); //在pos位置插入[beg,end)区间的数据,无返回值。(插入区间)
//erase 指定位置删除
d.erase(d.begin(), d.end()); //删除[beg,end)区间的数据,返回下一个数据的位置。
d.erase(d.begin()); //删除pos位置的数据,返回下一个数据的位置。
//clear 清除所有元素
d.clear(); //清空容器的所有数据
- 插入和删除提供的位置一定要是迭代器!
6 deque数据存取(at、operator[]、front、back)
//at 函数获取
d.at(i) //返回下标idx所指的数据
//operator[ ] 重载[ ]
d[i] //返回下标idx所指的数据
//front back 两个接口
d.front() //返回容器中第一个数据元素
d.back() //返回容器中最后一个数据元素
- 除了用迭代器获取deque容器中元素,[ ]和at也可以
7 deque排序(sort不是成员函数,是全局函数)
sort(d.begin(), d.end()); //对beg和end区间内元素进行从小到大排序
-
支持随机访问的的迭代器的容器,都可以利用sort算法直接对其进行排序
三、string(结构类似于vector)
1 string容器基本概念
- 本质:string是C++风格的字符串,而string本质上是一个类
str1.puch_back ('A'); //在str1末尾添加一个'A'字符,参数必须是字符形式
(1) string和char* 区别:
- char* 是一个指针
- string是一个类,类内部封装了char*,管理这个字符串,是一个char型的容器
- string管理char*所分配的内存,不用担心复制越界和取值越界,由类内部进行负责
#include <algorithm>
string str("hello");
reverse(str.begin(),str.end()); //反转字符串
string类常用的成员函数有:
str1.length(); //获取字符串长度
str1.size(); //获取字符串数量,等价于length()
str1.capacity(); //获取容量,容量包含了当前string里不必增加内存就能使用的字符数
str1.puch_back ('A'); //在str1末尾添加一个'A'字符,参数必须是字符形式
str1.resize(10); //表示设置当前string里的串大小,若设置大小大于当前串长度,则用字符\0来填充多余的.
str1.resize(10,char c); //设置串大小,若设置大小大于当前串长度,则用字符c来填充多余的
str1.reserve(10); //预定 //设置string里的串容量,不会填充数据.
str1.swap(str2); //替换str1 和 str2 的字符串
str1.clear(); //删除所有
str1.empty(); //判断为空, 为空返回true
2 string构造函数(类似vector)
string s1; //创建一个空的字符串
string s2(str) //使用字符串str初始化(传地址)
string s3(s2); //使用一个string对象初始化另一个string对象 (拷贝构造)(传对象)
string s4(10, 'a'); //10个字符a初始化
// string s5(vec.begin(), vec.end()); //没有区间拷贝vector
3 字符串长度获取(length、size、strlen)
(1)用string的成员方法length()获取字符串长度
//length()比较直观,表示的就是该字符串的长度。
string str="abc";
len = str.length()
//结果为3
(2)用string的成员方法size()获取字符串长度
//size()表示的是string这个容器中的元素个数。那么size()表示的就是这个vector(容器)中char的个数。
string str="abc";
len = str.size();
//结果为3
(3)用strlen获取字符串长度
//strlen同样也可以用于C++的string。但是需要用str.c_str()将C++ string转换为char*类型。
string str = "abc";
const char* c = str.c_str(); //指针常量(指向不可改,值可改)(eg.引用)
char* c = (char*)str.c_str();
const char* p = str.data();
int len = strlen(c);
4 string赋值操作 (operator=、assign)
//operator= 运算符重载
str1 = "hello world";
str2 = str1;
str3 ='a';
//assign 赋值 成员函数
/*assign() :赋值函数 ,里面会重新释放分配字符串内存 */
str1.assign("HELLO"); //str1="HELLO"
str1.assign("HELLO", 4); //str1="HELL" ,0位置4个字符
str1.assign("HELLO", 2, 3); //str1="LLO" ,2位置3个字符
str1.assign(5, 'c'); //str1="CCCCC",5个c
5 string字符串拼接(operator+= 重载、append)
- 实现在字符串末尾拼接字符串
//operator+= 重载
str1 += "爱玩游戏";
str1 += ':';
str1 += str2;
//append 附加 成员函数
str3.append(" love");
str3.append(" game abcde", 4);
str3.append(str2);
str3.append(str2, 4, 3); //从str2[4]开始3个字符
//字符串str2中从str2[4]开始的3个字符连接到字符串str3结尾
6 string查找和替换(find、rfind、replace)
-
find、rfind 查找
:查找指定字符是否存在,find查找是从左往右,rfind查找是从右往左。find找到字符后返回查找的第一个字符位置,找不到返回 -1 -
replace 替换
:在指定的位置替换字符串。replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串
//find 查找函数
string str("ABCDEFGABCD");
int n;
/*查找成功返回位置,查找失败,则n等于-1*/
/*find():从头查找某个字符串*/
n= str.find('A'); //查找"A",n=0;
n= str.find("AB"); //查找"AB",n=0;
n= str.find("BC",1); //从位置1处,查找"BC",n=1;
n= str.find("CDEfg",1,3); //从位置1处,查找"CDEfg"的前3个字符,等价于str.find("CDE",1),n=2;
//rfind 反查找函数
string str("ABCDEFGABCD");
int n;
/*rfind():反向(reverse)查找,从末尾处开始,向前查找*/
n= str.rfind("CD"); //从位置10开始向前查找,n=9
n= str.rfind("CD",5); //从位置5开始向前查找,n=2
n= str.rfind("CDEfg",5,3); //从位置5处,向前查找"CDEfg"的前3个字符,等价于str.rfind("CDE",5); ,所以n=2
//replace 替换函数
str1.replace(2,4, "ABCD"); //从下标为2的位置,替换4个字节,为"ABCD"
7 string字符串比较(compare)
- 字符串对比主要是用于比较两个字符串是否相等,判断谁大谁小的意义并不是很大。
-
字符串比较是按字符串的ASCII码进行对比
等于 返回 0
大于 返回 1
小于 返回 -1
//compare 比较函数
str1.compare(str2) == 0 //判断与字符串是否相等
str1.compare(“aaa”) == 0 //判断与字符串aaa是否相等
8 string字符存取(operator[] 重载、at )
//operator[] 重载
str[i]; //读取
str[0] = 'x' ; //通过[]重载取字符 ,写
//at 获取函数
str.at(i); //读取
str.at(1) = 'q'; //通过at函数获取字符,写
9 string插入和删除(insert、erase)
//insert (插入函数) 要具体位置
str1.insert (2,"ABC"); //在str1的下标为2的位置,插入"ABC"
str1.insert(2, 5, c); //在str1的下标为2的位置,插入5个'c'
//erase 删除函数
str1.erase(2); //删除下标为2的所以字符,比如: "ABCD" --> "AB"
str1.erase(2,1); //从下标为2的位置删除1个字符,比如: "ABCD" --> "ABD"
10 string子串获取(substr)
//substr 子串获取函数
str2=str1.substr(2); //提取str1的下标,从2到末尾,给str2
str2=str1.substr(2,3); //从str1的下标,从2开始3个字符给str2
11 C++ 中 string和char* 的区别
- char*:char *是一个指针,可以指向一个字符串数组,至于这个数组可以在栈上分配,也可以在堆上分配,堆得话就要你手动释放了。
//char* s = "string"; //内容是不可以改的
char s[ ] = "string"; //内容是可以改的
s[0] = 'j';
for (int i = 0; s[i] != '\0'; ++i)
{
cout << s[i];
}
char* p = new char[10]; //开辟到堆区
11.1 string转char*
-
有如下三种方法实现类型转换,分别是:
c_str(); data(); copy();
//1. c_str()方法
//注意:若不添加const,会报错invalid conversion from const char* to char *。char*要开辟新的空间,可以加上const或强制转化成char*。
string str=“world”;
const char *c = str.c_str(); //加const或等号右边用char* //常量指针是指针(指向可改,值不可改)
char *p = (char*)str.c_str(); p[0] = 'a'; //内容是可以改的
//c的值不可改
//2. data()方法
string str = "hello";
const char* p = str.data();//加const或等号右边用char*
char * p=(char*)str.data();
//3.copy()方法
string str="qweqwe";
char data[30];
str.copy(data, 3, 0);//0表示复制开始的位置,3代表复制的字符个数
11.2 char * 转string
//直接赋值
string s;
char *p = "hello";
s = p;
-
当我们定义了一个string,就不能用
scanf("%s",s)
和
printf("%s",s)
输入输出。主要是因为
%s
要求后面是对象的首地址
12 string和int的相互转换
12.1 int转换成string
//c++11标准增加了全局函数std::to_string:
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
12.2 string转换成int
// 1.atoi是 C 语言的库函数,atoi()不会做范围检查,如果超出范围的话,超出上界,则输出上界,超出下界,则输出下界;
// 2.stoi()会做范围检查,默认范围是在int的范围内的,如果超出范围的话则会runtime error!
atoi();//函数原型 int atoi(const char* str);
stoi();//函数原型 int atoi(const char* str);
atof();//浮点型
atol();//long型
#include<cstring> // 头文件
string s1("1234567");
char* s2 = "1234567";
char s3[] = "123";
int a = stoi(s1);
int b = atoi(s2);
int c = atoi(s1.c_str());
int d = atoi(s3);
版权声明:本文为uytguytgf原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。