1.string
#include <iostream>
#include <string>
1.1构造
//赋值构造
string str = "zxm";
//无参构造,构造一个空字符串,构造之后可以通过=进行赋值
string str2;
//用char *构造
string str3("zxm");
//重复字符构造,输出11个a
string(11,'a');
//拷贝构造 str2和str5内容是一样的
string str5(str2);
//移动拷贝 str2没有内容,移动到str6里去了
string str6(move(str2));
//用指定范围内的字符进行构造,从第四个下表开始,取三个给str7
string str7(str2,4,3);
//字符串拼接
string str8+str2+"111";
1.2 元素访问
string str="hello world";
str[1]='E';
str.at(1)='E';
//第一个字符
cout << str.front() << endl;
//最后一个字符
cout << str.back() << endl;
//data() c_str 获取数据
cout << str.data() <<endl;
1.3容量操作
//判断是否为空 返回0、1 true、false
string str = "hello world";
cout << boolalpha << str3.empty() <<endl;
//字符串中的大小和长度
cout << str.size() << endl;
cout << str.length() << endl;
//字符串对象最大的容量
cout str.max_size() << endl;
//截取前几个字符
cout << str.resize(10) << endl;
//已经分配的内存容量
cout << str.capacity() << endl;
//分配内存大小
str.reserve();
//没有用到的内存释放掉
str.shrink_to_fit();
1.4迭代器
迭代器:为容器类提供统一的遍历接口,不用管容器底层内存管理方式。
1.(正向)迭代器 iterator
2.(正向)只读迭代器 const_iterator
3.反向迭代器 reverse_iterator
4.反向只读迭代器 const_reverse_iterator
string str = "hello world";
//指向第一个位置
string::iterator it = str.begin();
//输出h
cout << *it <<endl;
//输出l
it+=3;
cout << *it < endl;
//可以修改,如果是只读迭代器的话,就不可以修改了
*it ='E'
//循环遍历
for(;it!=str.end();it++){
cout << *it <<endl;
}
反向迭代器:
string::reverse_iterator it = str.rbegin();
//循环遍历
for(;it!=str.rend();it++){
cout << *it <<endl;
}
1.5string比较相关操作
//==
string str="hello world";
string str2="Hello World";
cout << std::boolalpha <<(str==str2) <<endl; //返回true or false
//compare
cout << str.compare(str2) <<endl;
//判断是否以指定的内容开始或者结尾
cout << boolalpha << str.starts_with("hello") << endl;
cout << boolalpha << str.ends_with("jpg") <<endl; //可以判断后缀名
//判断字符串中是否含有某些内容
cout << boolalpha << str.contains("txt") <<endl;
1.6插入和删除操作
string str="hello world";
//在现有的字符串基础上再加E
str.push_back("E");
//把最后一个字符串给删除
str.pop_back();
//在字符串基础上追加内容,就是在最后开始追加
str.append(3,'A'); //追加三个A
str.append(3,'A').append(2,'B');
str.append(str2);
//从第三个字符开始追加
str.append(str2,3);
str.append("Nice");
str.append(str2.begin(),str2.begin()+3);
//insert() 在指定位置插入字符
str.insert(2,3,'C'); //从索引为2开始插入三个C
str.insert(2,str2,5,2);
//清除字符串的所有内容
str.clear();
//清楚指定位置
str.erase(2,2); //从2开始 清除两个字符
str.erase(str.begin()+2); //从str开始的第二个字符开始清除
ser.erase(str.begin()+2,str.begin()+5); //清除[2,5)字符
1.7 替换子串
string str = "hello world";
string str2="北国风光";
string str3 = "hello Cpp";
str.replace(2,1,str2) ; //索引为2的字符替换一个字符 替换成str2 he北国风光lo world
//取字符串
cout << str.substr(3) << endl; //从索引3开始提取
cout << str.substr(3,2) << endl; //从索引3开始提取2个字符
1.8查找
string str = "AAABBBCCCDDD"
//返回查到的第一个字符的索引号 找不到返回npos(-1)
cout << str.find("AA") <<endl;
int index = str.find("KDKD");
if(string::npos==index){
cout << "没找到" << endl;
}else{
cout << "找到了" <<endl;
}
//从后面往前找
str.rfind();
//找最先出现的字符的位置
str.find_first_of("EECD");
//返回B的索引
str.find_first_not_of("AAA");
//从后往前找
find_last_of();
find_last_not_of();
1.9其他操作
to_string(); //将数组转化为string
str+to_string(12);
//将string转换为数字
cout << stoi(str2,&n,16) << endl; //将str2转换为16进制的数字,返回转换的个数n
cout << n << endl;
//将string转换为浮点型:DOUBLE,float
cout << stod(str2) << endl;
stof;
//计算hash值
cout << hs(str) <<endl;
1.10 string_view
const char *s="望长城内外";
string_view sv = s;
这样 sv和s都是指向同一个地址。否则,正常的string会再会创建另一个地址把内容存进去 节省了内存空间
//移除六个字节
sv.remove_prefix(6);
cout << sv << endl;
//从后面移除字节数
sv.remove_suffix(6);
2.容器
2.1array
//头文件
#include<array>
//创建
array<int,5> arr = {1,2,3,4,5};
cout << arr[0] <<endl;
cout << arr.at(0) <<endl;
//填充 将这五个位置都给填充上
array<int,5> arr; //可以存储自己定义的数据类型
arr.fill(111);
for(auto &n :arr){
cout << n << endl; //输出:111 111 111 111 111
}
//使用迭代器遍历
array<int,5>::iterator it = ar.begin();
for(;it!=arr.end();it++){
cout << *it << endl;
}
2.2vector
动态的连续数组 大小是变化的
#include<vector>
//声明
vector<int> vec; //int 可以替换成对象
cout << vec.size() << endl;
cout << vec.capacity() << endl;
for(auto &n : vec){
cout << n << "\t";
}
//分配了三个元素的大小 用100来填充
vector<int> vec(3,100);
//分配了10个元素的大小 用0来填充
vector<int> vec(10);
#include<vector>
//声明
vector<int> vec(10); //分配十个内存大小
//插入
vec.push_back(10);
//输出地址
cout << (uintptr_t)vec.data() << endl;
//插入
vec.push_back(122);
//输出地址
cout << (uintptr_t)vec.data() << endl;
//大小
cout << vec.size() << endl;
//分配的大小
cout << vec.capacity() << endl;
for(auto &n : vec){
cout << n << "\t"; //输出
}
//分配了三个元素的大小 用100来填充
vector<int> vec(3,100);
//分配了10个元素的大小 用0来填充
vector<int> vec(10);
1.调用无参构造进行初始化
调用了三参构造和移动构造,移动构造将临时变量移动到地址
vector<User> vec(3);
//在末尾插入user
vec.push_back(User(1,"tom",22));
2.调用拷贝构造
vector<User> vec(3);
User u1(1,"tom",22);
vec.push_back(u1);
User u2(1,"Jey",22);
vec.push_back(u2);
首先是u1的三参构造,然后就是拷贝对象,因为要拷贝到里面那个位置上
首先是u2的三参构造,然后就是拷贝对象。然后u1又进行了一次对象拷贝
内存分配的问题。给u2的内存分配完成后,将u1拷贝到u2的前面的那个位置
3.能不能不进行拷贝或者移动
vec.emplace_back(2,"jj",21); //插入
只进行了一次三参构造
vec.emplace_back();
只进行了一次无参构造
vec.emplace(vec.begin()+1,3,"Le",4);
2.3.单向链表-forward_list
声明:
#include<forward_list>
forward_list<int> fs = {2,4,1,9,3}
forward_list<int> fs2 = {5,8,1,6,9}
forword_list<int>::iterator it = fs.begin();
it++;
只能通过自增的方式一步一步的往后移
擦除元素
it++;
it++;
fs.erase_after(it); // 擦除it后面的元素 9被擦除了
for(auto &i : fs){
cout << i << "\t";
}
合并元素
fs.merge(fs2); //fs和fs2合并在一起 但是是无序的
//可以先排序,再合并
fs.sort();
fs2.sort();
fs.merge(fs2); //这样合并之后就是有序的了 把fs2合并到fs里面 fs2就没有内容了
指定位置合并
fs.splice_after(it,fs2); //在1后面把指定的链表插入进去
移除指定的值
fs.remove(8); //移除8
//根据条件移除对应的内容
bool pre(const int &n){
return n<4;
}
fs.remove_if(pre); //把<4的内容移除掉 对fs的每个元素用提供的函数做判断
fs.remoce_if([] (const int& n){return n<4});
//升序
fs.sort();
//逆序,降序
bool cmp(const int &a,const int &b){
return a>b;
}
fs.sort(cmp);
fs.sort([](const int &a,const int &b){return a<b});
greater<int> gt;
fs.sort(gt);
fs.sort(greater<int>());
//移除连续重复的元素
fs.unique();
2.4.list双链表
和单链表类似
list<int> ls = {1,3,4,5,6,7}
list<int>::iterator it = ls.begin();
it++;
it++;
it--;
cont << *it <<endl;
2.5.栈stack
引入头文件
#include<stack>
stack<string> str_stack;
str_stack.push("zzz"); //入栈 简单的数据类型用push
//取栈顶数据
string str = str_stack.top();
//栈顶元素删除
str_stack.pop();
cout << str << endl;
//出栈
while(!str_stack.empty()){
string str = str_stack.top();
str_stack.pop();
cout << str << endl;
}
2.6.队列queue
引入头文件
#include<queue>
queue<const char *>q;
q.qush("张三");
q.emplace("赵六"); //多个数据
获取第一个元素
const char *s=q.front();
//出队
q.pop();
cout << s << endl;
循环一次出队
while(!q.empty()){
const char *s=q.front();
//出队
q.pop();
cout << s << endl;
}
2.7.双端队列priority_queue 优先队列
priority_queue<int> q;
q.push(10);
q.push(20);
q.push(15);
while(!q.empty()){
auto top = q.top(); //获取队首元素
q.pop();
cout << top <<endl;
}
输出:20 15 10 按照从大到小输出
可以从小到大输出
priority_queue<int,vector<int>,greater<int>> q; //参数:类型,容器,默认vector,比较器
q.push(10);
q.push(20);
q.push(15);
输出: 10 15 20
//如果存入的数据是自定义的类,那就需要重载一个<运算符 就可以用默认的比较器比较大小
priority_queue<Persion> q;
q.emplace(60,"Tom");
q.emplace(70,"Jerry");
q.emplace(65,"Lee");
//根据年龄比较大小
//重载<运算符
bool operator < (const Persion &p1,const Persion &p2){
return p1.getAge() < p2.getAge();
}
输出: 70 65 60
自定义比较器
方式一:模仿less定义的比较器
struct Comp{
bool operator()(const Persion &p1,const Persion &p2) const{
return p1.getAge() < p2.getAge();
}
};
priority_queue<Persion,vector<Persion>,Comp> q;
方式二:定义普通比较函数
bool cmp(const Persion &p1,const Persion &p2){
return p1.getAge() < p2.getAge();
}
typefdef bool (*cmp2) (const Persion &p1,const Persion &p2); //宏定义函数指针
priority_queue<Persion,vector<Persion>,cmp2> q(cmp);
方式三:通过lambda表达式定义比较函数
auto cmp3 = [](const Persion& p1,const Persion& p2){
return p1.getAge() < p2.getAge();
};
priority_queue<Persion,vector<Persion>,decltype(cmp3)> q(cmp3); //decltype自动类型推导
2.8.set
不重复
#include<set>
set<int> st {1,3,4,3} //输出:1 3 4 重复的删除掉了
vector<int> vec = {1,1,2,2,3,3,4,4,5,5};
set<int> st2(vec.begin(),vec.end()); //输出:1 2 3 4 5
判断两个元素是否相等
如何两个对象a和b相互不比较小于对方:!a<b && !a>b 那么认为他们等价
//插入元素节点
st.insert(0);
//把指定元素提取出来
set<int>::node_type node = st.extract(3); //把3提取出来
cout << node.value() << endl;
//合并集合 合并的是原先集合没有的
st.marge(st2)
返回元素的个数
st.count()
find:查找指定的值
返回指定的值的下边界,返回的是对应值的下标 返回的是迭代器
cout << *st.lower_bound(3) <<endl;
返回指定的值的上边界,返回的是对应值的下标 返回的是迭代器
cout << *st.upper_bound(3) <<endl;