1
|
extern int i; //声明i但不定义
|
正则表达式
知乎-正则表达式
可变数组vector
属于<vector>
库
常用方法
成员函数 |
作 用 |
vector() |
无参构造函数,将容器初始化为空 |
vector(int n) |
将容器初始化为有 n 个元素 |
vector(int n, const T & val) |
假定元素的类型是 T,此构造函数将容器初始化为有 n 个元素,每 个元素的值都是 val |
vector(iterator first, iterator last) |
first 和 last 可以是其他容器的迭代器。一般来说,本构造函数初始化的结果就是将 vector 容器的内容变成与其他容器上的区间 [first, last) —致 |
void clear() |
删除所有元素 |
bool empty() |
判断容器是否为空 |
emplace_back() |
更高效的void push_back(const T & val) |
void pop_back() |
删除容器末尾的元素 |
void push_back( const T & val) |
将 val 添加到容器末尾 |
int size() |
返回容器中元素的个数 |
T & front() |
返回容器中第一个元素的引用 |
T & back() |
返回容器中最后一个元素的引用 |
iterator insert(iterator i, const T & val) |
将 val 插入迭代器 i 指向的位置,返回 i |
iterator insert( iterator i, iterator first, iterator last) |
将其他容器上的区间 [first, last) 中的元素插入迭代器 i 指向的位置 |
iterator erase(iterator i) |
删除迭代器 i 指向的元素,返回值是被删元素后面的元素的迭代器 |
iterator erase(iterator first, iterator last) |
删除容器中的区间 [first, last) |
void swap( vector & v) |
将容器自身的内容和另一个同类型的容器 v 互换 |
rbegin()和rend()
队列Queue
C++队列Queue类成员函数如下:
back()返回最后一个元素
empty()如果队列空则返回真
front()返回第一个元素
pop()删除第一个元素
push()在末尾加入一个元素
size()返回队列中元素的个数
==实例==
初始化
1
2
3
4
5
6
7
8
9
10
|
std::deque<int> mydeck(3, 100); // 双端队列里初始化3个元素,都是100
std::list<int> mylist(2, 200); // list 容器里初始化2个元素,都是200
std::queue<int> first; // 初始化一个空队列
std::queue<int> second(mydeck); // 复制 mydeck 的内容初始化队列
std::queue<int, std::list<int> > third; // 初始化空队列,底层使用 list 容器
std::queue<int, std::list<int> > fourth(mylist); // 复制 mylist 的内容初始化队列,底层使用 list 容器
std::cout << "size of first: " << first.size() << std::endl; // 0
std::cout << "size of second: " << second.size() << std::endl; // 3
std::cout << "size of third: " << third.size() << std::endl; // 0
std::cout << "size of fourth: " << fourth.size() << std::endl; // 2
|
判空
1
2
3
4
|
std::queue<int> myqueue1;
bool empty1 = myqueue1.empty(); // true
std::queue<int> myqueue2({100,100});
bool empty2 = myqueue2.empty(); // false
|
获得元素个数
1
2
3
4
5
6
|
std::queue<int> myints;
std::cout << "0. size: " << myints.size() << std::endl; // 输出:0
for (int i = 0; i < 5; i++) myints.push(i);
std::cout << "1. size: " << myints.size() << std::endl; // 输出:5
myints.pop();
std::cout << "2. size: " << myints.size() << std::endl; // 输出:4
|
返回头元素引用
1
2
3
4
5
6
7
|
std::queue<int> myqueue3;
myqueue3.push(77);
myqueue3.push(66);
int& a1 = myqueue3.front(); // 77
int a2 = myqueue3.front(); // 77
myqueue3.front() = 88; // 给头元素77赋值为88
std::cout << "front:" << myqueue3.front() << std::endl; // 输出:88
|
返回末尾元素引用
1
2
3
4
5
6
7
|
std::queue<int> myqueue4;
myqueue4.push(77);
myqueue4.push(66);
int& b1 = myqueue4.back(); // 66
int b2 = myqueue4.back(); // 66
myqueue4.back() = 33; // 给末尾元素66赋值为33
std::cout << "front:" << myqueue4.front() << std::endl; // 输出:33
|
入队/出队
1
2
3
4
5
|
std::queue<int> myqueue5;
myqueue5.push(55); // 无返回值,入队了一个55,size()==1
myqueue5.push(45); // size()==2
myqueue5.pop(); // 无返回值,出队了一个55,size()==1
myqueue5.emplace(45);//另一种入队,其底层容器调用了emplace_back方法
|
交换
1
2
3
4
5
6
7
|
std::queue<int> teeth;
teeth.emplace(4); teeth.emplace(7);
std::queue<int> bags;
bags.emplace(4); bags.emplace(7); bags.emplace(7);
bags.swap(teeth);
std::cout << teeth.size() << std::endl; //输出:3
std::cout << bags.size() << std::endl; //输出:2
|
运算符 = != > >= < <=
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// [==]当两个队列front()内容一致,返回true
std::queue<int> q1, q2;
bool ret = q1 == q2; // ret为true
// [!=]当两个队列元素front()不相等,返回true
std::queue<int> q3, q4;
q3.push(1);
bool ret2 = q3 != q4; // ret2为true
// [>]左边队列的front()的元素大于右边队列pop的元素,则返回true.
std::queue<int> q5, q6;
q5.push(1); q5.push(2); q5.push(2);
q6.push(0); q6.push(2);
bool ret3 = q5 >= q6; // ret3为true,因为1大于0
|
头文件
algorithm(算法库)
==sort()==:
1
2
3
4
5
6
7
8
|
bool cmp(int a,int b){//此处为从大到小排序
return a>b;
}
std::sort(arr.begin(),arr.end());
std::sort(arr.begin(),arr.begin()+arr.size());
std::sort(arr.begin(),arr.begin()+arr.size(),cmp;
std::sort(arr.rbegin(),arr.rend());//反向迭代器,这样写也可以做到由大到小排
|
==__gcd(int,int)==:最大公约数 注意是两个’_’ 用go写就是这个
1
2
3
4
5
6
|
func gcd(a, b int) int {
for a != 0 {
a, b = b%a, a
}
return b
}
|
function
std::function是一个函数包装器,该函数包装器模板能包装任何类型的可调用实体,如普通函数,函数对象,lamda表达式等。包装器可拷贝,移动等,并且包装器类型仅仅依赖于调用特征,而不依赖于可调用元素自身的类型。std::function是C++11的新特性,包含在头文件中。
1
2
3
4
5
6
7
|
//定义void dfs(int,int,int){}
function<void (int,int,int)> dfs=[&](int x,int y,int gold){}
//function<int(int)> dfs =[&](int x)int{return x;} 省略"->"是不规范的lambda表达式,在很多编译器以及蓝桥上可通过,但力扣会报错
function<int(int)> dfs =[&](int x)->int{return x;};
[&,a,b]()->int{}//以只读的方式读入a,b,->后面表示返回
|
unordered_set
1
|
#include<unordered_set>
|
不能含有重复元素的容器
成员方法 |
功能 |
begin() |
返回指向容器中第一个元素的正向迭代器。 |
end(); |
返回指向容器中最后一个元素之后位置的正向迭代器。 |
cbegin() |
和 begin() 功能相同,只不过其返回的是 const 类型的正向迭代器。 |
cend() |
和 end() 功能相同,只不过其返回的是 const 类型的正向迭代器。 |
empty() |
若容器为空,则返回 true;否则 false。 |
size() |
返回当前容器中存有元素的个数。 |
max_size() |
返回容器所能容纳元素的最大个数,不同的操作系统,其返回值亦不相同。 |
find(key) |
查找以值为 key 的元素,如果找到,则返回一个指向该元素的正向迭代器;反之,则返回一个指向容器中最后一个元素之后位置的迭代器(如果 end() 方法返回的迭代器)。 |
count(key) |
在容器中查找值为 key 的元素的个数。 |
equal_range(key) |
返回一个 pair 对象,其包含 2 个迭代器,用于表明当前容器中值为 key 的元素所在的范围。 |
emplace() |
向容器中添加新元素,效率比 insert() 方法高。 |
emplace_hint() |
向容器中添加新元素,效率比 insert() 方法高。 |
insert() |
向容器中添加新元素。 |
erase() |
删除指定元素。 |
clear() |
清空容器,即删除容器中存储的所有元素。 |
swap() |
交换 2 个 unordered_map 容器存储的元素,前提是必须保证这 2 个容器的类型完全相等。 |
bucket_count() |
返回当前容器底层存储元素时,使用桶(一个线性链表代表一个桶)的数量。 |
max_bucket_count() |
返回当前系统中,unordered_map 容器底层最多可以使用多少桶。 |
bucket_size(n) |
返回第 n 个桶中存储元素的数量。 |
bucket(key) |
返回值为 key 的元素所在桶的编号。 |
load_factor() |
返回 unordered_map 容器中当前的负载因子。负载因子,指的是的当前容器中存储元素的数量(size())和使用桶数(bucket_count())的比值,即 load_factor() = size() / bucket_count()。 |
max_load_factor() |
返回或者设置当前 unordered_map 容器的负载因子。 |
rehash(n) |
将当前容器底层使用桶的数量设置为 n。 |
reserve() |
将存储桶的数量(也就是 bucket_count() 方法的返回值)设置为至少容纳count个元(不超过最大负载因子)所需的数量,并重新整理容器。 |
hash_function() |
返回当前容器使用的哈希函数对象。 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <iostream>
#include <string>
#include <unordered_set>
using namespace std;
int main()
{
//创建一个空的unordered_set容器
std::unordered_set<std::string> uset;
//给 uset 容器添加数据
uset.emplace("http://c.biancheng.net/java/");
uset.emplace("http://c.biancheng.net/c/");
uset.emplace("http://c.biancheng.net/python/");
//查看当前 uset 容器存储元素的个数
cout << "uset size = " << uset.size() << endl;
//遍历输出 uset 容器存储的所有元素
for (auto iter = uset.begin(); iter != uset.end(); ++iter) {
cout << *iter << endl;
}
return 0;
}
|
位、进制、原补反码
打印对应进制
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
#include <bitset> //输出二进制的头文件
using namespace std;
int main(){
int a = 2149580819;
cout << "八进制: " << oct << a << endl;
cout << "十进制: " << dec << a << endl;
cout << "十六进制: " << hex << a << endl;
cout << "二进制: " << bitset<sizeof(a)*8>(a) << endl;
return 0;
}
|
原码:
正数:对应的二进制码
负数:最高位符号位为1,其余是对应的二进制码
反码:
对原码按位取反,在c++中使用’~‘作为取反符号
补码:
反码加一,在程序中负数以补码形式存储
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=-1,b=100;
cout«bitset<sizeof(a)*8>(a)«" -1"«endl«bitset<sizeof(~a)*8>(~a)«" ~(-1)"«endl«endl«bitset<sizeof(b)*8>(b)«" 100"«endl«bitset<sizeof(~b)*8>(~b)«" ~(100)";
return 0;
}
c++基础
namespace(命名空间)
为了避免不同编译者定义不同变量的情况,使用命名空间独立开了各自的变量
使用命名空间可以使用using namespace全局引用,也可以使用::
局部引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <iostream>
namespace a{
class peo{
public:
int v;
void say(){
printf("%d",v);
}
};
}
using namespace a;
int main()
{
peo p;
p.v=1;
p.say();
return 0;
}
|
std命名空间
c++演变中,经历了一次巨大更新,为了避免老版本的东西无法使用,他们就把所有更新内容整到std内容空间中了,即不使用std的c++就是老版本c++,该改动中去掉了.h后缀,并给所有c的库加上了前缀’c’,如"math.h"被重命名为"cmath",std命名空间中添加了我们所熟知的cin>>
,cout<<
1
2
3
4
5
6
7
8
|
#include<iostream>
using namespace std;
int main(){
int x;
cin>>x;
cout<<x<<endl;
return 0;
}
|
把using namespace std;
写在全局并不规范,会增加命名冲突的风险,但是方便
输入输出
使用输入输出时,需要包含头文件iostream
,它包含了用于输入输出的对象,例如常见的cin
表示标准输入、cout
表示标准输出、cerr
表示标准错误
bool
c++支持bool,但是默认以1和0输出,如果要输出true or false则需要使用boolalpha
1
2
3
4
|
bool ok=true;
cout<<ok<<endl;//1
cout<<boolalpha<<ok<<endl;//true
cout<<noboolalpha<<ok<<endl;//1
|
new 和 delete
申请、释放内存
1
2
3
4
5
|
int *p = new int;//分配1个int型的内存空间
delete p;//释放内存
int *p = new int[10];//分配10个int型的内存空间
delete[] p;//释放内存
|
inline(内联函数)
即编译时,不是以调用的形式把函数放在外面调用,而是直接替换掉每一次调用
在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。
栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题,如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
inline const char *num_check(int v)
{
return (v % 2 > 0) ? "奇" : "偶";
}
int main(void)
{
int i;
for (i = 0; i < 100; i++)
printf("%02d %s\n", i, num_check(i));
return 0;
}
|
inline使用限制
inline 的使用是有所限制的,inline 只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如 while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。
inline仅是一个对编译器的建议
inline 函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。
建议 inline 函数的定义放在头文件中
其次,因为内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,要不然就成了非内联函数的调用了。所以,这要求每个调用了内联函数的文件都出现了该内联函数的定义。
因此,将内联函数的定义放在头文件里实现是合适的,省却你为每个文件实现一次的麻烦。
声明跟定义要一致:如果在每个文件里都实现一次该内联函数的话,那么,最好保证每个定义都是一样的,否则,将会引起未定义的行为。如果不是每个文件里的定义都一样,那么,编译器展开的是哪一个,那要看具体的编译器而定。所以,最好将内联函数定义放在头文件中。
类中的成员函数与inline
定义在类中的成员函数默认都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上 inline,否则就认为不是内联的。
1
2
3
4
5
6
7
8
|
// 头文件
class A
{
public:
void Foo(int x, int y);
}
// 定义文件,声明内联
inline void A::Foo(int x, int y){}
|
static(静态成员变量)
静态成员变量是一种特殊的成员变量,它被关键字static
修饰,它不占用额外内存,它是相同class的所有变量(如:stu li,stu wang)共用
string
属于<string>
库
==转char[]==
c_str()
,将string转为对应的const char[]
1
2
|
string s="hello";
const char * arr=s.c_str()
|
string的增删改查
==插入==
insert()
1
2
|
string s="012345";
s=s.insert(2,"hello");
|
s最终为:01hello2345
==删除==
erase()
1
2
3
4
5
6
7
|
string s1, s2, s3;
s1 = s2 = s3 = "1234567890";
s2.erase(5);
s3.erase(5, 3);
cout<< s1 <<endl;//1234567890
cout<< s2 <<endl;//12345
cout<< s3 <<endl;//1234590
|
==提取==
substr(),类似切片
1
2
3
|
string s="012345";
s=s.substr(2,3);
cout<<s;//234
|
==查找==
(1) find(string str,int n)
从第n个位置开始查找是否存在字符串str,若存在返回char[]下标,若不存在返回一个极大值(不一定是18446744073709551615)
1
2
3
|
string s="1234567890";
cout<<s.find("123",3)<<endl;//18446744073709551615
cout<<s.find("789",3);//6
|
(2) rfind(string str,int n)
直到下标n为止,查找字符串str
1
2
3
|
string s="1234567890";
cout<<s.find("123",3)<<endl;//0
cout<<s.find("789",3);//18446744073709551615
|
(3) find_first_of(string str)
查找str的某个字符,不需要整个字符串存在首次出现的位置
1
2
3
|
string s="1234567890";
cout<<s.find_first_of("879")<<endl;//6,7在第6个
cout<<s.find_first_of("012")<<endl;//0,1在第0个
|
switch…case…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
int main ()
{
char grade = 'D';
switch(grade)
{
case 'A' :
cout << "很棒!" << endl;
break;
case 'B' :
case 'C' :
cout << "做得好" << endl;
break;
case 'D' :
cout << "您通过了" << endl;
break;
case 'F' :
cout << "最好再试一下" << endl;
break;
default :
cout << "无效的成绩" << endl;
}
return 0;
}
|