文章目录
一、输入输出
while (cin >> n, n != -1)
效果与while (cin >> n && n != -1)
相同,表示在输入等于 − 1 -1 −1时结束循环;while (scanf("%d", &n) != EOF)
效果与while (cin >> n)
相同,在文件到达末尾时会结束循环;- 为实现类似于python中
split
函数,参见第3.3节;
二、vector
- 在类中直接定义
vector
并初始化时,需要注意一个问题:常用的vector<int> vec(100, 0)
这种格式直接放到类下面定义(而不是类函数中定义)时,编译器会把上面那个写法当做了函数定义,可以写作vector<int> vec = vector<int>(100, 0)
,详见: 类中vector的初始化问题; - 二维vector放入新行(数组)时,使用
vec.push_back(vector<int>(100, 1))
,表示在vec中添加了一个新行,行的长度为100,行中每个元素值为1; - 二维vector数组利用变量初始化行数和列数,并赋初值:
方法一vector<vector<int>> matrix(row, vector<int>(colum, value));
方法二vector<vector<int>> matrix; matrix.assign(row, vector<int>(colum, value));
- 将vector中元素倒序:使用
reverse(vec.begin(), vec.end())
,若要从某一位置开始,则使用reverse(vec.begin() + pos, vec.end())
(包含pos位置) - …
三、string
- 字符串就是字符数组加上结束符
'\0'
,例如使用string s = "C++";
得到的大小为3,但是使用char a[] = "C++";
得到的长度为4,原因是其结尾会暗含'\0'
(即第0个ASCII码),因此char a[] = "C++";
等价于char a[] = {'C', '+', '+', '\0'}
; - cin scanf等输入字符串时遇到空格就会停止,因此要是想把带空格的字符串比如
"hello world"
一次性输入到字符串变量内,可以使用fgets、getline、cin.getline
等函数,但是也有一些注意事项,比如fgets、cin.getline
函数会把回车读进去,详见此题的提交记录 760. 字符串长度、以及此题的视频讲解769. 替换字符; - 在python中有一个非常好用的函数叫
split
,C++中要实现类似的功能可以参考这篇文章C++中string如何实现字符串分割函数split(),相关题目的练习为AcWing 770. 单词替换;此外,一个更优雅的做法是调用sscanf
函数,见题636. 函数的独占时间; - 字符串末尾添加字符串为
.append()
,字符串末尾添加字符为.push_back()
; - 取子串方法为
str.substr(i)
表示取 [ i , e n d ) [i, end) [i,end),或者str.substr(i, j)
表示取 [ i , i + j ) [i, i + j) [i,i+j),其中 i i i、 j j j均为索引(下标)而不是迭代器;
四、map
- map默认排序方法为按照key值从小到大排序,即
map<int, string> Hash
等价于map<int, string, less<int>> Hash
,若要改为从大到小排序,则可写为map<int, string, greater<int>> Hash
; - 对map按key值进行自定义排序,例如对于
map<string, int> Hash
按照字符串长度来排序,则可以使用下面代码:
而后只需在初始化map时写为struct Compare { bool operator()(const string& str1, const string& str2) const { // 注意,此处const不可省略,否则报错 return str1.size() < str2.size(); } };
map<string, int, Compare > Hash
即可;
此外,若map的key值本身就是一个结构体类型或者class类型,则可以直接在定义key值时重载比较运算符,例子如下:
而后只需在初始化map时写为struct myKeyType { int age; int score; string name; bool operator < (myKeyType const& r) const { if (score != r.score) return score < r.score; else return age > r.age; } };
map<myKeyType, int,> Hash
即可; - 对map按value值进行自定义排序,一般方法是把map中的键值对放入vector中,再对vector利用sort排序:
map<string, int> Hash; ... vector<pair<string, int>> vec(Hash.begin(), Hash.end()); sort(vec.begin(), vec.end(), [](const pair<string, int>& a, const pair<string, int>& b) { return a.second > b.second; });
- 利用迭代器访问map键值对时,
iter->first
指key值,而iter->second
指value值; - map自带
upper_bound
函数和upper_bound
函数,调用为Hash.upper_bound(num)
;
五、priority_queue
- priority_queue默认为大根堆,即
priority_queue<int> Q
等价于priority_queue<int, vector<int>, less<int>()> Q;
而若要使用小根堆,则需要priority_queue<int, vector<int>, greater<int>()> Q;
- 自定义排序
按照second的降序排列
按照first的升序,再按照second的升序排列auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) { return a.second < b.second; }; priority_queue<pair<int, int>, vector<int, int>, decltype(cmp)> que(cmp);
typedef pair<int, int> P; struct cmp{ bool operator()(P a, P b) { if(p1.first==p2.first) return p1.second>p2.second; else return p1.first > p2.first; } }; priority_queue<P, vector<P>, cmp> que;
六、class
(1)析构函数
- …
(2) 继承
- …
七、const
- const写在函数名前,如
const int func(int n)
表示此函数的return类型是const类型; - const写在函数名后,如3.2节对map按key值自定义排序,表示此函数是一个常函数,函数中只能作读取操作,而不能作修改操作;
- const用在函数参数里,如
void func(const int &a)
,表示该参数在函数体中不能被修改;之所以加了引用符号&
是因为一般的形参的值修改并不会影响实参,只有在引用、指针参数、数组参数时才会使用const
修饰,详见此两个博客【c++】参数传递—const形参与实参和普通引用和const引用区别;
八、排序
sort
默认为升序排序,如果想要降序,可以使用sort(vec.begin(), vec.end(), greater<int>())
;sort
自定义排序
表示对points的行进行排序,排序依据为points的第二列元素的大小;sort(points.begin(), points.end(), [](const vector<int>& a, const vector<int>& b) { return a[2] < b[2]; });
- …
九、C++特性
(1)运算符重载
- …
(2)lambda函数
- …
(3)捕获
- …
十、常用STL函数
- 二分搜索用
upper_bound()
和lower_bound()
,前者指大于给定值的第一个迭代器,后者指大于等于给定值的第一个迭代器;而要想将“大于”改为“小于”,或者将“大于等于”改为“小于等于”,则需要在这两个函数的第四个参数位置写上greater<type>()
,详见关于lower_bound( )和upper_bound( )的常见用法 islower()
判断是否为小写英文字母,isupper()
判断是否为大写英文字母,isdigit()
判断是否为数字字符;max_element(vec.begin(), vec.end())
用于返回vec中的最大值迭代器位置(指针);max_element(vec.begin(), vec.end()) - vec.begin()
用于返回vec中的最大值索引(下标);*max_element(vec.begin(), vec.end())
用于返回vec中的最大值的数值;- 此外还能进行自定义比较,比如可以如下定义
bool cmp (int a, int b) { return abs(a) < abs(b); }
,然后将cmp
放入max_element
第三个参数即可;再或者,可以像sort
自定义排序一样借用lambda
函数:
max_element(a.begin(), a.end(), [](const int& a, const int& b){ return abs(a) < abs(b); });
- 返回数组第
k
k
k大的元素,可以使用STL库函数中的
nth_element(nums.begin(), k, nums.end())
,也可以参考快速排序源码思想中的RandomParitition
函数所构建出来的RandomSelect
函数,详情见《计算机算法设计与分析 第4版 ,王晓东编著 》第2.9章线性时间选择; - 可使用
reverse
函数将vector
元素、string
等翻转:reverse(vec.begin(), vec.end())
,如果需要从Pos_1位置开始(包括Pos_1位置),则reverse(vec.begin() + Pos_1, vec.end())
; accumulate
函数包含在#include<numeric>
头文件中,能够对vector
或数组等中的元素进行求和,其第一、二个参数分别为累加的开始和截止地址,第三个参数为累积初值,一般为0;- 当
vector
中元素类型为字符串类型时,求和操作就相当于字符串拼接操作,此时第三个参数可以写成""s
如accumulate(subs.begin(), subs.end(), ""s);
,表明累加初值为空字符串; - 此外,还可以在第四个参数上写上
multiplies<int>()
,这样即可实现对vector
或数组等中的元素进行连乘,第三个参数为连乘初值。
- 当
- …