【C++】vector/deque/string

  • Post author:
  • Post category:其他


文章目录



注意事项

//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(101);    //初始化了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);  2010   
//重新指定容器的长度为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);   151//重新指定容器的长度为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 版权协议,转载请附上原文出处链接和本声明。