C++常用知识点及STL操作

0 篇文章 0 订阅

一、类型转换

1、int与string互转
① int 转string
int/long/long long/unsigned int/ i=10;
string str=to_string(i) // unsigned long/unsigned long long/float/double/long double都可以用该方法
② string转int
string a="123";
int b=stoi(a) // stol:string->long  stoll:string->long long
int c=atoi(a.c_str()); // string转int
2、char与string互转
① char转string:
char ch=‘c’;
string s="";
s+=c; // 这时string可以直接与char相加得string
② string转char:
sting s="hello";
char ch=s[0]; // 下标取出来的是字符
3、字符大小写转换:
char ch='c';
ch=ch-'a'+'A'; // 小写转大写
ch=ch-'A'+'a'; // 大写转小写

二、常用操作

1、string:
① 常用操作
length() // 获取字符串长度
size()   // 获取字符串长度,与length一样
append() // 在string对象后面再附加一个字符串,也可以用+或+=
push_back()  // 在string对象后面附加一个字符
empty()  // 判断字符串是否为空
swap(string str) // 交换两个字符串

at(int index) // 获取下标为index的字符,也可以用[]
substr(size_t pos = 0,size_t len = npos) // 获取子串。获取 string 对象中从 pos 处开始的 len 个字符到string对象substr中去,并返回substr。
compare(size_t pos,size_t len,const string&str)const;    // 参数 pos 为比较字符串中第一个字符的位置,len 为比较字符串的长度,也可以用==、<等。当比较字符串比源字符串小时返回负数

// 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos
find(const string& str, size_type pos = 0) 
// 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找 s 的前 n 个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos
find(const char *s, size_type pos, size_type n)
// 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找字符 ch 。如果找到,则返回该字符首次出现的位置;否则,返回 string::npos
find(char ch, size_type pos = 0)
// 是从指定位置 pos (默认为字符串末尾)开始向前查找,直到字符串的首部,并返回第一次查找到匹配项时匹配项首字符的索引。换句话说,就是查找子字符串或字符最后一次出现的位置。与find一样,只是方向相反
rfind() 

insert(size_t pos, const string&str) // 在位置 pos 处插入字符串 str
insert(size_t pos, const char * s, size_t n) // 在位置 pos 处插入字符串 s 的前 n 个字符
insert(size_t pos, size_t n,char c) // 在位置 pos 处插入 n 个字符 c
erase(size_t pos = 0, size_t len = npos) // 删除从 pos 处开始的 n 个字符

getline(cin,str) // 从输入流中读取一行数据到 str,可以读取空格,只以回车换行分隔

例子

// 获取长度
string str("Hello,World!");
int strLen1 = str.length();
int strLen2 = str.size();
// 字符串拼接
string str1 = "hello,world!";
string str2 = "HELLO,WORLD!";
str1+=str2;
str1.append(str2);
str1.append("C string");
str1.push_back('a');
// 获取子串
string str("Hello,World!");
string subStr = str.substr(3,5);
cout << subStr << endl; // "lo,Wo"
// 从输入流中读取带空格的字符串
string str;
getline(cin, str); // 获取一行包含空格的字符串
cout << str; // 要包含头文件#include <string>
stringstream s(str); // 要包含头文件#include <sstream>
string temp;
while (s >> temp) // 按照空格进行拆分,并将结果输入到temp中
	cout << temp << "*";
② 初始化
// 创建空string
string str; 
// 直接用字符串常量来初始化string
string str("Hello!");
// 创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 c
string str(10,'a');
// 用一个 string 对象来初始化 string 对象(复制构造函数)
string str1("hello!");
string str2(str1);
③ 插入
// 插入
string str("abcdefgh");
str.insert(1,"INSERT"); // 在位置 1 处插入字符串 "INSERT"
cout << str << endl; // aINSERTbcdefgh
str.insert(10, 5, 'A'); // 在位置 10 处插入 5 个字符 'A'
cout << str << endl; // aINSERTbcdAAAAAefgh
④ 删除
str.erase(5,6); // 删除从索引位置 5 开始的 6 个字符
cout << str << endl; // str 为:aINSEAAAAefgh
⑤ 查找
// 查找子串出现的位置
string str("cat,dog,cat,pig,little cat,hotdog,little pig,angry dog");
size_t catPos = str.find("cat",0); // 从下标0开始寻找cat出现的下标
if (catPos == string::npos) 
    printf("没有找到字符串\n");
else{
    while (catPos != string::npos) {
        cout << "在索引 " << catPos << " 处找到字符串" << endl; // 0 8 23
        catPos = str.find("cat", catPos + 1);
    }
}
2、pair
① 初始化
// 初始化时赋值
pair<string, double> p("tomatoes", 3.25);
// 使用first、second赋值
pair<string, double> p;
p.first="light";
p.second=1;
//  使用make_pair来赋值
pair<string, double> p;
p=make_pair("shoe", 3); // make_pair是返回一个pair <类型,类型>  的数据
② 修改
// 取值
pair<string, double> p("tomatoes", 3.25);
cout<<p.first<<"\t"<<p.second<<endl;
// 修改
p.first="light";
p.second=1;
3、vector
① 常用操作
clear() // 清空
empty() // 判空
size()  // 向量存储的元素个数
capacity()  // 向量真实大小
push_back() // 在后面添加元素
pop_back()  // 删除末尾元素并不返回
front() // 返回第一个元素
back()  // 返回最后一个元素
begin() // 开始的迭代器
end()   // 指向最后一个元素的后面的迭代器

// 在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器
iterator insert( iterator loc, const TYPE &val ); 
// 在指定位置loc前插入num个值为val的元素
void insert( iterator loc, size_type num, const TYPE &val );  
// 在指定位置loc前插入区间[start, end)的所有元素
void insert( iterator loc, input_iterator start, input_iterator  end );  

// 删除迭代器loc对应的元素,erase的参数只能是迭代器
erase(iterator loc)
// 删除迭代器[begin,end)之间的元素
erase(iterator begin, iterator end)
② 初始化
vector<int> vec;        //声明一个int型向量
vector<int> vec(5);     //声明一个初始大小为5的int向量
vector<int> vec(10, 1); //声明一个初始大小为10且值都是1的向量
vector<int> vec(tmp);   //声明并用tmp向量初始化vec向量
vector<int> tmp(vec.begin(), vec.begin() + 3);  //用向量vec的第0个到第2个值初始化tmp
int arr[5] = {1, 2, 3, 4, 5};   
vector<int> vec(arr, arr + 5); //将arr数组的元素用于初始化vec向量
//说明:这里不包括arr[4]元素,末尾指针都是指结束元素的下一个元素,这个主要是为了和vec.end()指针统一。
③ 添加与修改
// push_back
vector<int> vec;
vec.push_back(1); // [1]
vec.push_back(2); // [1,2]
// insert
vector<int> vec1, vec2;
vec1.push_back(1);
vec1.push_back(2);
vec1.push_back(3);
vec1.push_back(4);
vec2.push_back(9);
vec2.push_back(9);
vec2.push_back(9);
vec2.insert(vec2.end(),vec1.begin(),vec1.end()); // 将vec1的元素插入到了vec2的后面 -> [9,9,9,1,2,3,4]
vec2.insert(vec2.begin(),10); // [10,9,9,9,1,2,3,4] 在vec2的第一个元素前面插入值10
vec2.insert(vec2.begin()+1, 3, 0); // [10,0,0,0,9,9,9,1,2,3,4] 
④ 删除
vec2.erase(vec2.begin()+1); // 删除第一个元素, [10,0,0,9,9,9,1,2,3,4] 
vec2.erase(vec2.begin()+1, vec2.begin()+4); // 删除[vec2[1],vec2[4]),[10,9,9,1,2,3,4] 
vec2.erase(find(vec2.begin(), vec2.end(), 9)); // 删除元素9,[10,9,1,2,3,4] 
⑤ 遍历
vector<int> vec;
// 用迭代器遍历
for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
    cout << *it << endl;
// 用长度遍历
for(int i=0;i<vec.size();i++)
	cout<<vec[i]<<endl;
⑥ 排序与其它操作
// 元素翻转
#include <algorithm>
reverse(vec.begin(), vec.end());
// 元素排序#include <algorithm>
sort(vec.begin(), vec.end()); //采用的是从小到大的排序
//如果想从大到小排序,可以采用上面反转函数,也可以采用下面方法:
bool Comp(const int& a, const int& b) { // 有时候要用static
    return a > b; // b是堆顶,所有元素都比它大,所以是小根堆,从大到小排序
}
sort(vec.begin(), vec.end(), Comp);
// 统计元素出现的次数
int num=count(vec.begin(),vec.end(),target);   //注意不是vector的类函数哟!
4、map
① map(默认按key升序)

note:当用map[key]取值时,即使key不存在也不会报错,而是会返回value的默认值,如int默认为0,bool默认为false,string默认为空。

  • 常用操作
begin()           返回指向map头部的迭代器
end()             返回指向map末尾的迭代器
empty()           如果map为空则返回true
erase()           删除一个元素
find()            查找一个元素
insert()          插入元素
clear()           删除所有元素

count()           返回指定元素出现的次数
max_size()        返回可以容纳的最大元素个数
size()            返回map中元素的个数
swap()            交换两个map

lower_bound()     返回键值>=给定元素的第一个位置
upper_bound()     返回键值>给定元素的第一个位置
rbegin()          返回一个指向map尾部的逆向迭代器
rend()            返回一个指向map头部的逆向迭代器
value_comp()      返回比较元素value的函数
key_comp()        返回比较元素key的函数
  • 初始化和添加
map<string, int> Map; // 声明,默认value是缺省值(int 为0,string为空字符串)
// 赋值
Map["abc"]=1;
Map.insert({"x", 1});
Map.insert(pair<string,int>("c",3));
Map.insert(make_pair<string,int>("d",4));
  • 删除元素
map<string,int>::iterator it=Map.begin();  
Map.erase(it);//通过迭代器删除  
string key="abc";  
Map.erase(key);//通过key删除  

// 将iter++写在for循环中会导致程序行为不可知
// 因为某一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用
// 在迭代过程中删除的正确写法
// 1. 使用删除之前的迭代器定位下一个元素。STL建议的使用方式
for(map<string,int>::iterator iter=Map.begin();iter!=Map.end();){
    cout<<iter->first<<":"<<iter->second<<endl;
    Map.erase(iter++);
}
// 2. erase() 成员函数返回下一个元素的迭代器
for(map<string,int>::iterator iter=Map.begin();iter!=Map.end();){
    cout<<iter->first<<":"<<iter->second<<endl;
    iter=Map.erase(iter);
}
  • 修改和查找数据
// 修改
Map["abc"]=4; // 修改key为abc对应的value
// 查找方法1
map<string,int>::iterator res= Map.find("abc"); // 查找失败返回end(),查找成功返回迭代器
if(res!=Map.end())
	cout<<key->second<<endl;
// 查找方法2
int cnt=Map.count("abc"); // 返回值为1或者0,1返回存在,0返回不存在
// 因为在map类型中所有数据的Key值都是不同的,所以被count的数要么存在1次,要么不存在
  • 排序
// 为了实现快速查找,map内部本身就是按序存储的(比如红黑树),这也是作为key的类型必须能够进行<运算比较的原因
// 按key排序
map<string, int, less<string> > m; // 默认是less,按key进行升序排列
map<string, int, greater<string> > m; // 按照key进行降序排列
// 按key的长度进行排序(重载()运算符)
struct CmpByKeyLength {
  bool operator()(const string& k1, const string& k2) {
    return k1.length() < k2.length(); // 其它的长度都比堆顶k2小,是从小到大排序
  }
};
map<string, int, CmpByKeyLength> m; // 按照key的长度从小到大排序
// 按value排序
// 自定义排序方法
struct CmpByValue {
  bool operator()(const pair<string, int>& lhs, const pair<string, int>& rhs) {
    return lhs.second < rhs.second; // 按照第二个元素从小到大排序
  }
};
map<string, int> m;
// 把map中元素转存到vector中 
vector<pair<string, int> > vec(m.begin(), m.end());
// 利用sort函数对vector进行排序
sort(vec.begin(), vec.end(), CmpByValue());
for (int i = 0; i != name_score_vec.size(); ++i)
    cout << vec[i] << endl;
② unordered_map
  • 初始化与添加
unordered_map<char, int> ch; // 声明
// 直接赋值
for(int i=0;i<10;i++)
    ch[i+'a']=0; 
// 使用insert函数
ch.insert({'x', 1 });
ch.insert(pair<char, int>('x', 2));
ch.insert(make_pair('y', 2));
  • 遍历
void Show(unordered_map<char, int> m){
    for(unordered_map<char, int>::iterator iter=m.begin(); iter!=m.end();iter++)
        cout<<iter->first<<"\t"<<iter->second<<endl; // iter是迭代器指针,要用'->',不能用'.'
}
5、queue
① queue
  • 常用操作
push(x) // 将x添加到队列的末端。
pop() 	//弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
front() // 访问队首元素,即最早被压入队列的元素。
back()	// 访问队尾元素,即最后被压入队列的元素。
empty() // 判空,当队列空时,返回true。
size() 	// 访问队列中的元素个数
  • 遍历
queue<int> q;
while(!q.empty()){
	cout<<q.front()<<"\t";
	q.pop();
}
② dequeue(双端队列)
  • 常用操作
front()     // 获取队头元素
back()      // 获取队尾元素
push_back() // 在尾部插入一个元素
push_front()// 在头部插入一个元素
pop_back()  // 删除尾部的一个元素
pop_front() // 删除头部的一个元素
  • 初始化与遍历
deque<int> q(20); // 初始化一个有20个元素的双端队列
// 用迭代器
for (deque<int>::iterator it=q.begin();it != q.end(); it++) 
	cout << *it << "\t";
// 用下标
for(int i=0;i<q.size();i++)
	cout << q[i] <<"\t";
③ priority_queue(优先级队列)
  • 常用操作
top() 	// 返回队顶元素,没有front函数
// 所有queue的操作它都有
  • 默认排序规则
priority_queue<int> p; // 默认小根堆,从大到小排列
priority_queue<int, vector<int>, less<int> > p; // 大根堆:表示其他都比堆顶小,从大到小排序,最后两个> >中间需要用空格 
priority_queue<int, vector<int>, greater<int> > p; // 小根堆:表示其他都比堆顶大,从小到大排序
  • 自定义排序规则
// 结构体的运算符重载:
struct people
{
	string name;
	int age;
	friend bool operator< (people p1, people p2) // 重载小于号
	{
		return p1.age < p2.age; // f2是根,其值最大,相当于less,这是大根堆,反之则是小根堆
	}
} people; // 定义结构体别名
// 比较运算符外置:
struct peolpe
{
	string name;
	int age;
}people; //定义结构体别名

struct cmp
{
	bool operator() (people p1, people p2) // 重载括号
	{
		return p1.age > p2.age; // 与上面类似,小根堆,从小到大排序
	}
};
  • 例子
struct cmp{
	bool operator() (pair<int, int> p1, pair<int, int> p2){
		return p1.first>p2.first; 
	}
};
priority_queue<pair<int, int>, vector<pair<int,int>>, cmp> captial; // 小根堆,从小到大排序
captial.push(make_pair(Capital[i], Profits[i]));
// 等价于:priority_queue<pair<int, int>, vector<pair<int,int>>, greater<pair<int,int> > captial; 
6、stack
① 常用操作
empty() // 判空,若为空则返回true
pop() 	// 删除栈顶元素但不返回
push() 	// 在栈顶增加元素
top()	// 返回栈顶元素
size() 	// 返回栈中元素个数
② 遍历
stack<int> s;
while(!s.empty()){
	cout << s.top() << "\t";
	s.pop();
}
7、set

set不允许有重复元素但是默认有序,要有重复元素要用multiset。另外还有unordered_set和unordered_multiset,并且set不能用[]进行取值

① 常用操作
begin()	  	// 返回set容器的第一个元素对应的迭代器
end()  	// 返回set容器的最后一个元素对应的迭代器
clear() 	// 删除set容器中的所有的元素
empty()   	// 判断set容器是否为空
max_size() 	// 返回set容器可能包含的元素最大个数
size()    // 返回当前set容器中的元素个数
rbegin()  	// 返回的值和end()相同
rend()   	// 返回的值和rbegin()相同
find() 		// 返回一个指向被查找的元素对应的迭代器
count()  	// 用来查找set中某个某个键值出现的次数,只会为0或1

lower_bound() // 返回第一个大于或等于给定关键值的元素对应的迭代器
upper_bound() // 返回第一个大于给定关键值的元素对应的迭代器
equal_range() // 返回一对定位器,分别表示 第一个大于或等于给定关键值的元素对应的迭代器 和 第一个大于给定关键值的元素对应的迭代器,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于s.end()

例子

set<int> s;
s.insert(1);
s.insert(2);
s.insert(5);
cout << "第一个大于或等于3的元素: " << *s.lower_bound(3) << endl; // 5
cout << "第一个大于或等于2的元素: " <<*s.lower_bound(2) << endl; // 2
cout << "第一个大于2的元素: " <<*s.upper_bound(2) << endl; // 5
cout << "第一个大于或等于2的元素: " <<  *s.equal_range(2).first << endl; // 2
cout << "第一个大于2的元素: " << *s.equal_range(2).second << endl; // 5
cout << "set中4出现的次数是 :"<<s.count(4)<<endl; // 0
② 创建与初始化
// 创建默认的set
set<int> seta; // 默认是小于比较器less<int>的set,即从小到大排序
set<int, greater<int> > setb; //创建一个带大于比较器的set,需包含头文件functional,即从大到小排序
// 用数组或集合初始化set
int a[5] = {1,2,3,4,5};
set<int > setc(a,a+5); //数组a初始化一个set;
set<int > setd(setc.begin(),setc.end()); //setc初始化一个set
set<int > sete(setd); //拷贝构造创建set
③ 插入
set<int> s;
// 插入单一元素
s.insert(2); // [2]
// 插入多个元素
int a[4] = {11,12,13,14};
s.insert(a,a+4); //将区间[a[0],a[4])里的元素插入容器, [2,11,12,13,14]
④ 删除
// set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。
int a[] = {1,2,3,4,5,6,7,8,9,10};
set<int> s(a, a+10); // [a[0],a[9])
// 删除单个元素
s.erase(7); // [1,2,3,4,5,6,8,9,10]
// 删除迭代器对应的元素
s.erase(s.begin()); // [2,3,4,5,6,8,9,10]
// 删除指定区间的元素
set<int>::iterator iter1=s.begin(); // s[0],不能iter1=s.begin()+1,会报错
iter1++; // s[1], 不能用iter1+=4来移动迭代器,只能使用++
set<int>::iterator iter2=s.begin();
iter2++; // s[1]
iter2++; // s[2]
iter2++; // s[3]
s.erase(iter1, iter2); // 删除[s[1],s[3])->[2,5,6,8,9,10]
⑤ 修改
set<int>::iterator iter=s.begin();
(*iter)=10; // 这样会报错,set是无法修改的
⑥ 查找与遍历
int a[] = {1,2,3};
set<int> s(a,a+3);
// 使用count
if(s.count(2)==0)
	cout << "2 不存在";
else
	cout << "2 存在";
// 使用find
set<int>::iterator iter;
if((iter = s.find(2)) != s.end())
    cout<<*iter<<endl;//输出为2
// 遍历
for(set<int>::iterator iter=s.begin();iter!=s.end();iter++)
    cout<<*iter<<"\t";
⑦ 排序
struct cmp{
    bool operator () (const int &a, const int &b){
        return a > b; // b是堆顶,所有元素都比它大,所以是小根堆,从大到小排序
    }
};
set<int, cmp>s; //自定义排序函数构造set

三、小知识

1、最大公约数:
int m=15, n=9;
while((r=m%n)!=0){ // r=6	r=3
	m=n;		   // m=9	m=6
	n=r;		   // n=6	n=3
}
return n;
// 一句话递归
int gcd(int x, int y){
	return x%y==0?y:gcd(y, x%y);
}
2、ASCII码
A:65
a:97

参考链接:
https://www.cnblogs.com/panweiwei/p/6657583.html
https://www.cnblogs.com/tomcao/p/6011413.html
https://blog.csdn.net/iicy266/article/details/11906189?utm_source=tuicool&utm_medium=referral
https://blog.csdn.net/shuaizhijun/article/details/88955081
https://www.cnblogs.com/caiyishuai/p/8646345.html
https://www.cnblogs.com/tongye/archive/2019/04/24/10760154.html
https://www.cnblogs.com/zhonghuasong/p/5975979.html
https://www.cnblogs.com/vranger/p/3341361.html
https://www.cnblogs.com/hdk1993/p/5809180.html

以上只是学习笔记,如有错误欢迎指正~
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值