STL

STL

fetch150zy

c++标准模板库

C++ 标准模板库

一、序列式容器

1.1.array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 构造函数
array<type, size> a; // 值不确定
array<type, size> a {}; // 值全为默认值
array<type, size> a {val_1, val_2, ...};// 初始化列表
array<type, size> a {b}; // () =

// 遍历
// begin() end() cbegin() cend()
// rbegin() rend() crbegin() crend()
for (auto i: a);
for (type i: a);
for (array<type, size>::iterator it = b.begin(); it != b.end(); ++it);
for (array<type, size>::reverse_iterator it = b.rbegin(); it != b.rend(); ++it);

// 元素访问
a.at(idx); // 有边界检查
a[idx]; // 无边界检查
a.front(); // 返回array首元素
a.back(); // 返回array尾元素
a.data(); // 返回首元素指针
get<idx>(array& a) // 获取idx位置的引用

// array容量大小相关
a.empty(); // 判断容器是否为空
a.size(); // 返回容纳的元素数
a.max_size(); // 返回可容纳的最大元素数

// 其它操作
a.fill(val); // 将array容器中元素全部赋值为val
a.swap(b); // 交换两个容器里面的元素

1.2.vector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 构造函数
vector<type> v; // 空vector
vector<type> v(size); // 元素个数为size
vector<type> v(size, val); // 个数为size且值为val
vector<type> v(v1); // = {}
vector<type> v(v1.begin(), v1.end()); // {}
iota(v.begin(), v.end(), start_num); // 批量递增赋值

// 容器遍历相关
// begin() end() cbegin() cend() rbegin() rend() crbegin() crend()
for (vector<type>::iterator it = v.begin(); it != v.end(); ++it);
for (vector<type>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit);
for (auto i: v);
for (vector<type>::iterator::value_type item: v);
for (vector<type>::reverse_iterator::value_type ritem: v);
for (int i = 0; i < v.size(); ++i);

// 添加元素
push_back(); // 向容器尾部添加一个元素
insert(); // 向容器指定位置插入元素
emplace_back(); // 容器尾部插入元素(引用)
emplace(); // 容器指定位置插入元素(引用)

// 删除元素
erase(); // 删除容器中指定位置元素
pop_back(); // 删除容器中最后一个元素
clear(); // 清空容器中所有元素

// 访问元素
at(); // 返回指定位置元素的引用
front(); // 返回首元素的引用
back(); // 返回尾元素的引用
v[idx]; // 返回idx位置的元素引用

// 容器大小相关
v.empty(); // 判断容器中是否为空
v.size(); // 返回元素个数
v.capacity(); // 当前能容纳最大元素个数
v.max_size(); // 能容纳最大元素个数
v.reserve(); // 重分配大小(增加容器的容量)
v.resize(); // 改变实际元素的个数
v.shrink_to_fit(); // 将内存减小到等于当前元素实际所使用的大小

// 其他操作
swap(v1); // 交换两个同类型向量的数据
assign(); // 设置向量元素值

1.3.deque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 构造函数
deque<type> d; // 空deque
deque<type> d(size); // 指定deque大小
deque<type> d(size, val); // 指定大小并赋初值
deque<type> d(d1); // {} =
deque<type> d(d.begin(), b.begin());
deque<type> d {...}; // 初始化

// deque遍历相关
// begin(), end(), rbegin(), rend(), cbegin(), cend(), crbegin(), crend()

// 其他操作
assign(); // 替换
swap(); // 交换

// 元素访问
d[idx]; // 返回索引位置元素
back(); // 返回尾元素
front(); // 返回首元素
at(idx); // 返回索引位置元素

// 添加元素
insert(); // 任意位置插入元素
push_back(); // 尾插
push_front(); // 首插
empalce(); // 指定位置插入新元素(引用)
empalce_back(); // 尾插新元素(引用)
empalce_front(); // 首插新元素(引用)

// 删除元素
pop_back(); // 尾删
pop_front(); // 首删
clear(); // 清空
erase(); // 删除指定元素

// 容量大小相关
max_size(); // 双端队列的最大容量
resize(); // 改变双端队列的大小
shrink_to_fit(); // 调整到适合双端队列的大小
size(); // 返回元素个数
empty(); // 判断双端队列是否为空

1.4.list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 构造list容器的常见方式
list<type> L;
list<type> L(size);
list<type> L(size, val);
list<type> L {L1}; // () =
list<type> L {L1.begin(), L1.end()};
list<type> L {...}; // 初始化

// 添加元素
emplace(); // 指定位置插入一个新元素(引用)
emplace_back(); // 容器尾部插入一个新元素(引用)
emplace_front(); // 容器开头插入一个新元素(引用)
insert(); // 插入到迭代器指向的位置之前
push_back(); // 尾加元素
push_front(); // 首加元素

// 删除元素
pop_back(); // 尾删
pop_front(); // 首删
erase(); // 删除指定迭代器位置的元素
clear(); // 清空容器

// 容量大小相关
empty(); // 判断是否为空
size(); // 列表中存在元素数
max_size(); // 列表最大大小
resize(); // 改变容器大小

// 元素访问相关
front(); // 返回首元素引用
back(); // 返回尾元素引用
l[idx]; // 返回索引位置元素

// 其它操作
swap(); // 交换
reverse(); // 翻转
sort(); // 升序排列
merge(); // 合并两个排序的列表
splice(); // 新列表插入到调用列表中
unique(); // 去重
assign(); // 替换

1.5.forward_list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 构造函数
forward_list<type> L;
forward_list<type> L(size);
forward_list<type> L(size, val);
forward_list<type> L {L1}; // () =
forward_list<type> L {L1.begin(), L1.end()};
forward_list<type> L {...}; // 初始化

// 迭代器
before_begin(); // 第一个元素之前的位置
cbefore_begin();
begin(); end(); cbegin(); cend();

// 容量大小下相关
empty(); // 判断容器是否为空
max_size(); // 容器所能包含元素的最大数量
resize(); // 调整容器大小

// 添加元素
push_front(); // 容器头部添加一个新元素
emplace_front(); // 与push_front相同但效率高
emplace_after(); // insert_after相同但更快
insert_after(); // 指定位置之后插入并返回新的迭代器
splice_after(); // 插入一段区间

// 删除元素
pop_front(); // 删除容器头部的元素
erase_after(); // 删除指定位置的元素
clear(); // 清空容器
remove(); // 按值删除
remove_if(); // 按条件删除

// 元素访问
front(); // 返回第一个元素的引用

// 其他函数
sort(); // 排序
merge(); // 合并
reverse(); // 翻转
unique(); // 去重
assign(); // 替换

二、关联式容器

2.1.map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 构造函数
map<key_type, val_type> m;
map<key_type, val_type> m {{key_1, val_1}, {key_2, val_2}, ...};
map<key_type, val_type> m {make_pair(key_1, val_1), ...};
map<key_type, val_type> m {m1}; // = ()
map<key_type, val_type> m {m1.begin(), m1.end()};
map<key_type, val_type, less<key_type> > m; // 升序(默认)
map<key_type, val_type, greater<key_type> > m; // 降序

// 遍历相关迭代器
// begin(); end(); cbegin(); cend();
// rbegin(); rend(); crbegin(); crend();

// 添加删除元素
insert(); // 插入键值对
emplace(); // 插入键值对,比insert高效
emplace_hint(); // 和emplace类似,但是必须要传入一个迭代器
erase(); // 删除某个key对应的键值对
clear(); // 清空map

// 查找相关
[key];
at(key);
find(); // 查找某个key,若查到返回该key的迭代器
lower_bound(); // 返回>=某个key的迭代器
upper_bound(); // 返回>某个key的迭代器
equal_range(); // 返回lower_bound和upper_bound组成的pair

// 容量大小相关
size(); // 返回当前键值对的个数
max_size(); // 返回map所能容纳的最大键值对个数
empty(); // 判断map是否为空

// 其他函数
swap(); // 交换两个map对象,前提是两个map对象类型大小相同
count(); // 查找某个key的个数(1 or 0)

2.2.set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 构造函数
set<type> s;
set<type> s {...};
set<type> s {s1}; // () =
set<type> s {s1.begin(), s1.end()};
set<type, greater<type> > s;
set<type, less<type> > s;

// 遍历相关
// begin(); end(); cbegin(); cend();
// rbegin(); rend(); cbegin(); crend();

// 添加删除元素
insert(); // 指定位置插入
erase(); // 删除指定位置的元素
clear(); // 清空集合
emplace(); // 指定位置插入元素(引用,效率更高)
emplace_hint(); // 与emplace类似,不过必须指定一个迭代器参数

// 查找
find(); // 查找(返回迭代器)
lower_bound(); // 返回>=待查找元素的第一个元素的迭代器
upper_bound(); // 返回>待查找元素的第一个元素的迭代器
equal_range(); // 返回upper_bound和lower_bound组成的pair

// 容量大小相关
empty(); // 判断集合是否为空
size(); // 返回集合大小
max_size(); // 返回set容器能容纳的最大元素个数

set_intersection(); //(取集合交集)
set_union(); //(取集合并集)
set_difference(); //(取集合差集)
set_symmetric_difference(); //(取集合对称差集)

// 其它操作
swap(); // 交换两个集合容器
count(); // 查找某个元素的个数(0 or 1)

2.3.multi_map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 构造函数
multimap<key_type, val_type> m;
multimap<key_type, val_type> m {{key_1, val_1}, {key_2, val_2}, ...};
multimap<key_type, val_type> m {make_pair(key_1, val_1), ...};
multimap<key_type, val_type> m {m1};
multimap<key_type, val_type> m {m1.begin(), m1.end()};
multimap<key_type, val_type, less<key_type> > m;
multimap<key_type, val_type, greater<key_type> > m;

// 迭代器
// begin(); end(); cbegin(); cend();
// rbegin(); rend(); crbegin(); crend();

multimap<keys_type, vals_type>::iterator it = mmp.find(key);
for(auto cnt = 0; cnt != mmap.count(key); cnt++, it++)
cout << it->first << ":" << it->second << endl;

multimap<keys_type, vals_type>::iterator bg = mmp.lower_bound(key), ed = mmp.upper_bound(key);
for(auto it = bg; it != ed; it++)
cout << it->first << ":" << it->second << endl;

multimap<keys_type, vals_type>::iterator bg = mmp.equal_range(key).first, ed = mmp.equal_range(key).second;
for(auto it = bg; it != ed; it++)
cout << it->first << ":" << it->second << endl;

// 查找
find(); // 若找到返回其迭代器,否则返回尾迭代器
lower_bound(); // 第一个>=key的迭代器
upper_bound(); // 第一个>key的迭代器
equal_range(); // pair对象,key所在区间
count(); // 返回键为key的键值对个数

// 容量大小
empty(); // 判断容器是否为空
size(); // 返回容器中键值对个数
max_size(); // 容器所能容纳最大键值对个数

// 添加删除元素
insert(); // 添加键值对
emplace(); // 添加键值对(比insert高效)
emplace_hint(); // 添加新键值对(必须传入迭代器)
erase(); // 删除删除指定键值对
clear(); // 清空容器

// multimap没有重载[]操作符以及at()函数,主要是因为multimap一个键对应多个值

2.4.multi_set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 构造函数
multiset<type> s;
multiset<type> s {s1}; // () =
multiset<type> s {s1.begin(), s1.end()};
multiset<type> s {val_1, val_2, ...}; // 初始化
multiset<type, greater<type> > s;
multiset<type, less<type> > s;

// 迭代器
// begin(); end(); cbegin(); cend();
// rbegin(); rend(); crbegin(); crend();

// 查找
find(); // 找到返回其对应迭代器,没找到返回尾迭代器
lower_bound(); // >=
upper_bound(); // >
equal_range(); // 对应val的区间
count(); // 对应val的个数

// 容量大小
empty(); // 判断容器是否为空
size(); // 元素个数
max_size(); // 容器能容纳最大元素个数

// 添加删除元素
insert(); // 指定位置插入元素
emplace(); // 比insert块
emplace_hint(); // 相比emplace必须传入一个迭代器
erase(); // 删除指定元素

2.5.pair

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 重写<<操作符
template<typename T>
ostream& operator<<(ostream& os, pair<T, T> p) {
return os << "(" << p.first << ", " << p.second << ")";
}

// 重写>>操作符
template<typename T>
istream& operator>>(istream& is, pair<T, T>& p) {
return is >> p.first >> p.second;
}

// pair的构造函数
pair<type, type> p;
p = make_pair(val_1, val_2); // 通过make_pair赋值
pair<type, type> p {val_1, val_2}; // 初始化,()也行
pair<type, type> p (p1); // 构造拷贝
pair<type, type> p = p1;

// pair的访问
p.first == get<0>(p);
p.second == get<1>(p);
// 绑定到tie
//exp;
string name;
int16_t age;
tie(name, age) = make_pair("mars", 19);

三、无序关联容器

3.1.unordered_map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 构造函数
unordered_map<type, type> m;
unordered_map<type, type> m {{key_1, val_1}, {key_2, val_2}, ...};
unordered_map<type, type> m {m1};
unordered_map<type, type> m {m1.begin(), m1.end()};

// 遍历相关迭代器
begin(); end(); cbegin(); cend();

// 添加删除元素
m[key] = val; // 若key值存在,替换该key对应的val,若不存在则添加该键值对
m.at(key) = val; // 若key值存在,替换,若不存在报out_of_range
emplace(); // 添加新键值对(效率比insert高)
emplace_hint(); // 与emplace相比必须传入一个迭代器参数
insert(); // 插入新键值对
erase(); // 删除指定键值对
clear(); // 清空容器

// 容量大小相关
empty(); // 判断容器是否为空
size(); // 返回容器中键值对的个数
max_size(); // 返回容器所能容纳的最大键值对个数

// 查询相关
find(key); // 若找到,返回该键值对对应的迭代器,没找到返回尾迭代器
count(key); // 返回以key为键的键值对的个数
equal_range(key); // 返回pair,其包含 2 个迭代器,键为key的键值的范围
bucket_count(); // 返回存储键值对,使用桶(一个线性链表代表一个桶)的数量
max_bucket_count(); // 返回当前系统中,unordered_map 容器底层最多可以使用多少桶
bucket_size(n); // 返回第 n 个桶中存储键值对的数量。
bucket(key); // 返回以 key 为键的键值对所在桶的编号。

// 其他常用函数
swap(); // 交换两个相同类型的容器
load_factor(); // 返回 unordered_map 容器中当前的负载因子
max_load_factor(); // 返回或者设置当前 unordered_map 容器的负载因子
rehash(n); // 将当前容器底层使用桶的数量设置为n
reserve(); // 将桶的数量设置为至少容纳(不超过最大负载因子)所需的数量
hash_function(); // 返回当前容器使用的哈希函数对象

3.2.unordered_multimap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 构造函数
unordered_multimap<type, type> m;
unordered_multimap<type, type> m {m1}; // = ()
unordered_multimap<type, type> m {m1.begin(), m1.end()};
unordered_multimap<type, type> m {{key_1, val_1}, ...};

// 迭代器
// begin(); end(); cbegin(); cend();

// 容量大小相关
size(); // 返回键值对个数
max_size(); // 容器容纳最大键值对个数

// 查找
find(); // 返回查找位置的迭代器
count(); // 返回以key为键的键值对的个数
equal_range(); // key的键值对区间
bucket_count(); // 桶的数量
max_bucket_count(); // 底层桶的最大数量
bucket_size(); // 返回第n个桶中的键值对中的数量
bucket(); // 返回以key为键的键值对的桶编号


// 添加删除元素
emplace(); // 向容器中添加新键值对(比insert快)
emplace_hint(); // 与emplace区别在于必须传入迭代器
insert(); // 插入键值对
erase(); // 删除键值对
clear(); // 清空容器

// 其他函数
swap(); // 交换两个相同容器
load_factor(); // 返回负载因子
max_load_factor(); // 返回或设置负载因子
rehash(); // 设置桶的数量为n
reserve(); // 将桶的数量设置为至少容纳(不超过最大负载因子)所需的数量
hash_function(); // 返回当前容器使用的哈希函数

3.3.unordered_set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 构造函数
unordered_set<type> s;
unordered_set<type> s {s1}; // () =
unordered_set<type> s {s1.begin(), s1.end()};
unordered_set<type> s {val_1, val_2, ...};

// 迭代器
// begin(); end(); cbegin(); cend();

// 容量大小相关
empty(); // 判断容器是否为空
size(); // 返回集合中元素的个数
max_size(); // 容器所能容纳的最大元素个数

// 查找
find(); // 返回查找位置的正向迭代器
count(); // 返回容器中键为key的键值对的个数
equal_range(); // key键值对所在区间
bucket_count(); // 使用桶的数量
max_bucket_count(); // 桶的最大数量
bucket_size(); // 返回第n个桶储存元素的数量
bucket(); // 返回key的键值对所在桶的编号

// 插入删除元素
emplace(); // 指定位置插入键值对(比insert快)
emplace_hint(); // 与emplace区别在于必须传入一个迭代器
insert(); // 在指定位置插入键值对
erase(); // 删除指定位置键值对
clear(); // 清空容器

// 其他函数
load_factor(); // 返回负载因子
max_load_factor(); // 返回或者设置负载因子
rehash(n); // 将当前容器底层使用桶的数量设置为n
reserve(); // 将桶的数量设置为至少容纳(不超过最大负载因子)所需的数量
hash_function(); // 返回当前容器使用的哈希函数对象
swap(); // 交换两个相同容器

3.4.unordered_multiset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 构造函数
unordered_multiset<type> m;
unordered_multiset<type> m {m1}; // = ()
unordered_multiset<type> m {m1.begin(), m1.end()};
unordered_multiset<type> m {val_1, val_2, ...};

// 迭代器
// begin(); end(); cbegin(); cend();

// 容量大小相关
empty(); // 判断当前容器是否为空
size(); // 返回集合元素的个数
max_size(); // 返回容器所能容纳的最大元素个数

// 查找相关
find(); // 返回对应元素的迭代器
count(); // 返回对应元素的个数
equal_range(); // 返回对应元素所在区间
bucket_count(); // 返回使用桶的数量
max_bucket_count(); // 最多使用桶的数量
bucket_size(); // 返回第n个桶中存储元素的数量
bucket(); // 返回当前元素所在桶的编号

// 插入删除元素
emplace(); // 插入元素(比insert快)
emplace_hint(); // 与emplace相比必须传入一个迭代器
insert(); // 指定位置插入元素
erase(); // 删除指定位置元素
clear(); // 清空容器

// 其他函数
load_factor(); // 返回当前负载因子
max_load_factor(); // 返回或设置当前负载因子
rehash(); // 设置底层容器使用桶的数量
reserve(); // 将桶的数量设置为至少容纳(不超过最大负载因子)所需的数量
hash_function(); // 返回当前使用的hash函数
swap(); // 交换两个相同容器

四、容器适配器

4.1.stack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 构造stack常用方式
stack<type> s;
stack<type> s {s1}; // ()也行,也可通过其他容器初始化
// 默认stack使用deque容器,也可指定其他容器
stack<type, list<type> > s;

// stack常见操作
empty(); // 判断栈空
size(); // 栈大小
top(); // 返回栈顶元素
push(); // 压栈
pop(); // 弹栈
emplace(); // 栈顶生成对象
swap(); // 交换

4.2.queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// queue的常见创建方式
queue<type> q;
queue<type> q {q1}; // ()也行,也可通过其他容器初始化
// 默认queue使用了deque来作为容器,也可以指定其他容器
queue<type, list<type> > q;

// queue常见操作
front(); // 返回首元素引用
back(); // 返回尾元素引用
push(); // 入队列
pop(); // 出队列
size(); // 队列大小
empty(); // 判断队列空
emplace(); // 尾部入队(引用)
swap(); // 交换

4.3.priority_queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 创建对象
priority_queue<type, vector<type>, less<type> > pq; // 默认降序(优先级最高的先出队)
priority_queue<type, vector<type>, greater<type> > pq; // 升序(优先级最低的先出队)
// 对于自定义的结构类型需要自己重载比较运算符(可以看出this指针指向的相当于传入的第一个参数this)
struct Node { // 重载<运算符
int x, y;
bool operator<(const Node& a) const {
return a.x == this->x ? a.y > this->y : a.x > this->x;
}
}
// 也可在结构体外重载<运算符
bool operator<(const Node& this, const Node& a) {
return a.x == this.x ? this.y < a.y : this.x < a.x;
}

// 基本操作
push(); // 新元素插入优先队列。
pop(); // 优先级最高的元素从队列中删除
top(); // 寻址优先队列的最顶层元素
size(); // 返回优先队列的大小
empty(); // 验证队列是否为空
swap(); // 优先队列的元素与具有相同类型和大小的另一个队列交换
emplace(); // 优先队列的顶部插入一个新元素(引用)

五、其他

5.1.bitset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 构造函数
bitset<n> b; // n位全为0
bitset<n> bu {unsigned u}; // 将无符号整型二进制形式存在bu中
bitset<n> bs {string}; // 将string类型字符串按位存在bs中

// 常用操作
|(or); &(and); ~(not); ^(XOR); <<(left); >>(right);

// 常用函数
size(); // 返回大小(位数)
count(); // 返回1的个数
any(); // 返回是否有1
none(); // 返回是否没有1
set(); // 全都变成1
set(p); // 将第p + 1位变成1
set(p, x); // 将第p + 1位变成x(x非0的化就为1)
reset(); // 全都变成0
reset(p); // 将第p + 1位变成0
flip(); // 全都取反
flip(p); // 将第p + 1位取反
to_ulong(); // 返回它转换为unsigned long的结果,如果超出范围则报错
to_ullong(); // 返回它转换为unsigned long long的结果,如果超出范围则报错
to_string(); // 返回它转换为string的结果

5.2.tuple

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 重写<<操作符
template<typename T>
ostream& operator<<(ostream& os, tuple<T, T, T> t) {
auto [x, y, z] = t;
return os << "(" << x << ", " << y << ", " << z << ")";
}
// 重写>>操作符
template<typename T>
istream& operator>>(istream& in, tuple<T, T, T>& t) {
return in >> get<0>(t) >> get<1>(t) >> get<2>(t);
}
// tuple的构造函数
tuple<int, int, int> t = make_tuple(1, 2, 3); // 通过make_tuple
tuple<int, int, int> t (t1); // 构造拷贝
tuple<int, int, int> t = t1;
tuple<int, int, int> t {val-1, val_2, val_3}; // 初始化
tuple<int, int, int> t (val_1, val_2, val_3);
// tuple元素的访问
auto [x, y, z] = t;
get<0>(t), get<1>(t), get<2>(t);
// tuple常用函数
t1.swap(t2); // 前提是两个tuple类型相同
tuple_size<decltype(t)>::value; // 获取该tuple对象的元素个数
tie(x, y, z) = make_tuple(1, "str", 1.0); // 绑定到tie
auto t = tuple_cat(t1, t2); // 合并tuple

5.3.init-list

1
2
initializer_list<type> L {...};				// 初始化
max(L); // 获取最大元素

5.4.string

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* char* */
strcpy(s1, s2); // 复制字符串s2到s1
strcat(s1, s2); // 连接字符串s2到字符串s1后面
strlen(s1); // 获取s1的长度
strcmp(s1, s2); // 比较s1和s2
strchr(s1, ch); // 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置
strstr(s1 ,s2); // 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置




/* string */

// string类的构造函数
string str1; // 生成空字符串
string str(str); // 生成str的复制品,str为C_string or C++_string
string str(str, start_index, string_length); // 下标start_index开始,长度string_length的部分,str为C_string or C++_string
string str(char* C_string, int char_length); // 截取C类型字符串前length个字符
string str(int n, char ch); // n个ch字符拼接
string str(string CPP_string, int start_index); // 截取从start_index位置开始到末尾的子串

// 与stringstream的读写
stringstream ss;
string s1, s2("hello");
ss << s2; // write to stream
ss >> s1; // read from stream
getline(ss, s1); // read from stream

// string的显示
s.copy(char* c, len, pos); // 将string类型赋值给一个C_string
s.c_str(); // 将string以C_string类型返回
s.data(); // 以字符数组返回

// string的交换
s.swap(ss); // 交换s和ss

// string的赋值
s = "abc"; // 整个字符串的赋值
s.assign("bcd");
s.at(idx) = ch; // 单个字符的赋值
s[idx] = ch;
s.front() = ch; // 修改第一个字符
s.back() = ch; // 修改最后一个字符

// string的大小和容量
s.size() == s.length(); // 获取字符串s的长度
s.max_size(); // string对象最多包含的字符数
s.capacity(); // 重新分配内存之前string对象最多能包含的字符数
s.reserve(size); // 保留一定内存以容纳一定数量的字符

// string的字符串比较
// 直接通过 > >= < <= == != 来比较string对象,或string与C_string对象
// compare函数
A.compare(B); // 比较A与B
A.compare(A_begin, A_length, B); // A字符串从A_begin开始长度为A_length的字串与B比较
A.compare(A_begin, A_length, B, B_begin, B_length); // A子串与B子串比较
// exp:
A.compare(7, 3, B, 1, 5);

// string的插入(拼接)
string S;
S.push_back(char); // 在S字符串末尾加上char字符
S.insert(S.begin() + pos, char); // 在S串pos位置处插入char字符
S.append(str); // S后接str
S += str; // S后接str


// string 对象的遍历
for (int i = 0; i < s.size(); ++i); // C_style
for (auto i: s); // C++_style
for (string::iterator::value_type i: s);
// 正向迭代器
auto iter = s.begin(); // string::iterator iter = s1.begin();
for ( ; iter < s.end(); ++iter);
// 反向迭代器
auto riter = s.rbegin(); // string::reverse_iterator riter = s1.rbegin();
for ( ; riter < s.rend(); ++riter);

// string的删除
iterator erase(iterator p); // 删除字符串中p所指的字符
iterator erase(iterator first, iterator last); // 删除字符串中迭代器区间[first,last)上所有字符
string& erase(size_t pos, size_t len); // 删除字符串中从索引位置pos开始的len个字符
void clear(); // 删除字符串中所有字符

// string的字符替换
string& replace(size_t pos, size_t n, const char *s);
// 将当前字符串从pos索引开始的n个字符,替换成字符串s
string& replace(size_t pos, size_t n, size_t n1, char c); // 将当前字符串从pos索引开始的n个字符,替换成n1个字符c
string& replace(iterator i1, iterator i2, const char* s);//将当前字符串[i1,i2)区间中的字符串替换为字符串s

// string的大小写转换
tolower(char), toupper(char);
transform(s.begin(), s.end(), s.begin(),[](unsigned char c) { return toupper(c); });
// or
transform(s.begin(), s.end(), s.begin(), ::tolower);

// string的查找
size_t find (const char* s, size_t pos = 0) const;
//在当前字符串的pos索引位置开始,查找子串s,返回找到的位置索引,-1表示查找不到子串
size_t find (char c, size_t pos = 0) const;
//在当前字符串的pos索引位置开始,查找字符c,返回找到的位置索引-1表示查找不到字符
size_t rfind (const char* s, size_t pos = npos) const;
//在当前字符串的pos索引位置开始,反向查找子串s,返回找到的位置索引,-1表示查找不到子串
size_t rfind (charc, size_t pos = npos) const;
//在当前字符串的pos索引位置开始,反向查找字符c,返回找到的位置索引,-1表示查找不到字符
size_t find_first_of (const char* s, size_t pos = 0) const;
//在当前字符串的pos索引位置开始,查找子串s的字符,返回找到的位置索引,-1表示查找不到字符
size_t find_first_not_of (const char* s, size_t pos = 0) const;
//在当前字符串的pos索引位置开始,查找第一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到字符
size_t find_last_of(const char* s, size_t pos = npos) const;
//在当前字符串的pos索引位置开始,查找最后一个位于子串s的字符,返回找到的位置索引,-1表示查找不到字符
size_t find_last_not_of (const char* s, size_t pos = npos) const;
//在当前字符串的pos索引位置开始,查找最后一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到子串

// string的排序
sort(s.begin(), s.end());

// string的分割/截取字符串
// use strtok
char str[] = "I,am,a,student; hello world!";
const char *split = ",; !";
char *p2 = strtok(str, split);
while( p2 != nullptr ) {
cout<<p2<<endl;
p2 = strtok(nullptr, split);
}
// use substr
s1.substr(s_begin, s_length);

六、算法

6.1.sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
sort(first, last);									// 对数组和容器的区间进行排序(默认升序)
// exp:
vector<int> v {...};
sort(v.begin(), v.end(), less<int>); // 升序
sort(v.begin(), v.end(), grearter<int>); // 降序
sort(v.rbegin(), v.rend(), less<int>); // 降序
sort(v.rbegin(), v.rend(), greater<int>); // 升序
// 也可自定义比较函数
bool cmp(const int& a, const int& b) {
return a > b;
} // 降序
bool cmp(const int& a, const int& b) {
return a < b;
} // 升序
sort(v.begin(), v.end(), cmp);
// 对于自定义类型,可以选择重载操作符
struct A{
int x, y;
bool operator<(const A& a) const {
return this->x < a.x;
} // 升序(重载小于号)
bool operator>(const A& a) const {
return this->x > a.x;
} // 降序(重载大于号)
}
// 也可在结构体外重载操作符
bool operator<(const A& a, const A& b) {
return a.x < b.x;
} // 升序(重载小于号)
bool operator>(const A& a, const A& b) {
return a.x > b.x;
} // 降序(重载大于号)



stable_sort(first, last); // 与sort区别在于不会改变相同元素的相对位置
partial_sort(first, middle, last); // 筛选出最小的middle-first个数放在middle~first区间里
partial_sort_copy(first, last, result_first, result_last); // result_last-result_first个数排序放在result_first~result_last中
is_sorted(first, last); // 检测是否排好序(默认升序排列)
is_sorted_until(first, last); // 比is_sorted多一个返回首个无序元素的迭代器
nth_element(first, nth, last); // 将应该位于第nth位的元素放好,保证左右两侧大小关系(类似快排的一趟)

6.2.merge

1
2
3
4
5
6
7
8
9
10
merge(first_1, last_1, first_2, last_2, res_iter);			// 合并两个序列并放到容器中去
// exp:
int a[sizeA] = {...}, b[sizeB] = {...};
vector<int> res(sizeA+sizeB);
merge(a, a+sizeA, b, b+sizeB, res.begin());

inplace_merge(first, middle, last); // 主要将一个容器中两个有序部分合并
// exp:
int a[] = {..., ...};
implace_merge(a, a+mid, a+last);

6.3.find

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
find(first, last, val);
find_if(first, last, self_rule); // 相比find允许自定义查找规则
find_if_not(first, last, self_rule);
// exp:
// 自定义查找规则
bool cmp(int i) {
return ((i%2)==1);
} // 查找奇数
struct cmp {
bool operator()(const int& i) {
return ((i%2)==1);
}
};



find_end(first_main, last_main, first_sub, last_sub); // 查找子序列在主序列中最后出现的位置
find_end(first_main, last_main, first_sub, last_sub, self_rule);// 也可自定义查找规则
find_first_of(first_main, last_main, first_sub, last_sub, self_rule);// 主序列中任意一个元素与子序列中的元素匹配
// exp:
bool cmp(int i, int j) {
return (i%j==0);
} // 查找满足i%j==0
struct cmp {
bool operator()(const int& i, const int& j) {
return (i%j==0);
}
};
vector<int> v {1, 2, 3, 4, 8, 12, 18, 1, 2, 3};
int arr[] = {1, 2, 3};
vector<int>::iterator it = find_end(first_main, last_main, first_sub, last_sub, cmp);
int pos = it - first_main;



adjacent_find(first, last); // 查找连续两个相同的元素,也可自定义查找规则
adjacent_find(first, last, self_rule);
// exp:
vector<int> v {1, 2, 3, 4, 4, 7, 7, 9};
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
bool cmp(int i, int j) {
return (i==j);
} // 查找连续两个相同元素
struct cmp {
bool operator()(const int& _Left, const int& _Right) {
return (_Left == _Right);
}
};
it = adjacent_find(v.begin(), v.end(), cmp);



search(first_main, last_main, first_sub, last_sub); // 与find_end()相对,子序列首次出现的位置
search(first_main, last_main, first_sub, last_sub, self_rule); // 自定义匹配规则
search_n(first_main, last_main, n, val, self_rule); // 也可以自定义匹配规则
// exp:
int a[] = {1, 2, 3, 4, 5, 5, 5, 6, 7, 9};
auto it = search_n(a, a+size, 3, 5);

6.4.partition

1
2
3
4
5
6
7
8
9
10
11
12
partition(first, last, rule);			// 按照分组规则进行分组,返回分界线(第二组的第一个元素)
// exp:
bool cmp(int i) {
return (i%2==1);
}
vector<int> v {...};
auto bound = partition(v.begin(), v.end(), cmp);

stable_partition(first, last, rule); // 与partition()相比进行分组的时候不改变相对位置
partition_copy(first, last, res_1, res_2, rule);// 不改变相对位置且不修改原序列(拷贝),返回pair<iterator, iterator>

partition(first, last, rule); // 针对已经分过组的元素但不知道边界

6.5.bound

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 前提是有序
upper_bound(first, last, val); // 查找第一个大于等于某个元素的位置(迭代器)
lower_bound(first, last, val); // 查找第一个大于某个元素的位置(迭代器)
equal_range(first, last, val); // 查找某个元素所在的区间(pair<iterator, iterator>)
binary_search(first, last, val, rule); // 返回bool值,返回是否查找到目标元素(也可自定义查找规则)



all_of(first, last, func); // 所有都满足条件
any_of(first, last, func); // 任意一个满足条件
none_of(first, last, func); // 全都不满足条件
//exp:
vector<int> v{...};
int val = 0XFF;6
none_of(v.begin(), v.end(), [val](int vals)->bool{return val < vals ? true : false;});

6.6.equal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 用来比较两个序列,也可自定义比较规则
equal(first_iter_1, last_iter_1, first_iter_2);
equal(first_iter_1, last_iter_1, first_iter_2, last_iter_2);
equal(first_iter_1, last_iter_1, first_iter_2, self_rule);
equal(first_iter_1, last_iter_1, first_iter_2, last_iter_2, self_rule);



// 比较两个序列,可自定义比较规则,还能指出不匹配的位置
mismatch(first_1, last_1, first_2);
mismatch(first_1, last_1, first_2, last_2);
mismatch(first_1, last_1, first_2, self_rule);
mismatch(first_1, last_1, first_2, last_2, self_rule);
// 返回pair<iter_1, iter_2>
// exp:
vector<int> v1 {...};
vector<int> v2 {...};
auto pr = mismatch(v1.begin(), v1.end(), v2.begin());
auto iter_1 = pr.first;
auto iter_2 = pr.second;



// 比较字典序(字符串排序算法)
lexicographical_compare(first_1, last_1, first_2, last_2, cmp);

6.7.permutation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 一般用于全排列
next_permutation(first, last); // 字典升序
prev_permutation(first, last); // 字典降序
is_permutation(first_1, last_1, first_2, last_2); // 用于检查一个序列是不是另一个序列的排列
// exp:
vector<int> range {1,2,3,4}; // 初始时是最小排列
do {
for (auto i: range) cout << i << " ";
cout << endl;
}while(next_permutation(begin(range), end(range)));



vector<string> words { "one", "two", "three", "four"}; // 初始时不是最小排列
while(next_permutation(begin(words), end(words))); // 先到最小排列位置然后再输出
do {
for (auto i: words) cout << i << endl;
} while(next_permutation(begin(words), end(words)));



// 找到最小排列
vector<string> words { "one", "two", "three", "four"};
for (auto iter = begin(words); iter != end(words)-1 ;++iter)
iter_swap(iter, min_element(iter, end(words)));
for (auto i: words) cout << i << " ";
cout << endl;


// 通过生成副本来减小开销
vector<string> words {"one","two", "three", "four"};
auto words_copy = words;
do {
for (auto i: words) cout << i << " ";
cout << endl;
next_permutation(begin(words), end(words));
}while(words != words_copy);

6.8.copy

1
2
3
4
5
6
7
copy_n(source_first, n, res_first);					// 拷贝source中的n个元素到res中(res已初始化)
copy_n(source_first, n, inserter(res, res_first)); // res为空时
copy_if(source_first, source_last, res_first, self_rule);// 依照规则拷贝指定数据到res中(res已初始化)
copy_if(source_first, source_last, inserter(res, res_first), self_rule);// res为空
copy_backward(first_src, last_src, last_res); // 反向拷贝到res(顺序不变)
reverse_copy(first_src, last_src, first_res); // 逆序拷贝(目标序列反向)
reverse_copy(first_src, last_src, inserter(res, first_res)); // res为空

6.9.unique

1
2
unique(first_src, last_src);						// 去除相邻重复元素
unique(first_src, last_src, self_rule); // 也可自定义去除规矩

6.10.rotate

1
2
3
rotate(first_src, mid_src, last_src);						// 旋转序列,返回第一个元素的迭代器
rotate_copy(first_src, mid_src, last_src, first_res); // 旋转序列副本
rotate_copy(first_src, mid_src, last_src, inserter(res, first_res));// res为空

6.11.others

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// move
move(first_src, last_src, first_res); // 将目标序列移动到指定位置

// swap_ranges
swap_ranges(first_1, last_1, first_2); // 交换last_1-first_1个元素

// remove
remove(first, last, val);
//exp:
auto end_it = remove(v.begin(), v.end(), val);
for (auto it = v.begin(); it != end_it; ++it) cout << *it << " ";cout << endl;
// remove_copy
remove_copy(first_src, last_src, first_res, val); // res不为空
remove_copy(first_src, last_src, inserter(res, first_res), val);// res为空
// remove_if
remove_if(first, last, self_rule);
// remove_copy_if
remove_copy_if(first_src, last_src, first_res, self_rule);// res不为空
remove_copy_if(first_src, last_src, inserter(res, first_res), self_rule);// res为空

// fill, fill_n
fill(first, last, val); // 将指定区间元素全部置为val
fill_n(first_res, n, val); // 从指定位置开始后面n个元素置val(res不为空)
fill_n(inserter(res, first_res), n, val); // res为空

// generate, generate_n
generate(first, last, self_func); // 通过func在指定区间生成元素
generate_n(first, n, self_func); // 从指定位置开始通过func生成n个元素

// transform
transform(first, last, res_first, [](int i){return i+10;}); // 一元函数
transform(first_1, last_1, first_2, res_first, [](int a, int b){return a+b;});// 二元函数

// replace
replace(first, last, old_val, new_val); // 在指定区间内用新值替换旧值
replace(first, last, self_func, new_val); // 根据函数替换指定元素
replace_copy(first, last, res_first, old_val, new_val); // 产生副本

七、迭代器

7.1.reverse_iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 构造
reverse_iterator<iter_type> my_reiter;
reverse_iterator<iter_type> my_reiter {...}; // 初始化 () =

// 操作符
* 返回当前迭代器指向元素的引用
+ 返回一个反向迭代器,其指向距离当前指向的元素之后 n 个位置的元素
++
+= 当前反向迭代器前进 n 个位置
- 返回一个反向迭代器,其指向距离当前指向的元素之前 n 个位置的元素
--
-= 当前反向迭代器后退 n 个位置
-> 返回一个指针,其指向当前迭代器指向的元素
[n] 访问和当前反向迭代器相距 n 个位置处的元素

7.2.insert_iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 分类
insert_iterator; // 指定位置插入元素
front_insert_iterator; // 在指定容器头部插入元素
back_insert_iterator; // 在指定容器尾部插入元素

// back_insert_iterator
back_insert_iterator<container> it (container);
it = val; // 添加元素(尾加)

// front_insert_iterator
front_insert_iterator<container> it (container);
it = val; // 添加元素(首加)

// insert_iterator
insert_iterator<container> it (container, pos);
it = val; // 添加元素(在指定位置pos)

7.3.others

1
2
3
4
5
6
advance(it, n);			//it前进或后退n个位置
distance(first, last); //计算first和last之间的距离
begin(container); //返回容器第一个元素的迭代器
end(container); //返回容器的最后一个迭代器
prev(it); //返回一个指向上一个位置处的迭代器
next(it); //返回一个指向下一个位置处的迭代器

C plus plus

一、输入输出

1.1.C-style

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* standard input and output */
// get a char
scanf("%c", &c);
c = getchar();
c = fgetchar();
c = fgetc(stdin);
// get a string
scanf("%s", s); // can't read space, tab, enter etc
gets(s); // unsafe and easy to overflow
gets_s(s, size); // more safe than gets, but not yet fully supported
fgets(s, size, stdin); // recommend using this, it's easy and safe

// output a char
printf("%c", c);
putchar(c);
fputchar(c);
fputc(c, stdout);
// output a string
printf("%s", s);
puts(s);
fputs(s, stdout);





/* freopen */
FILE *fpin = freopen("data.in", "r", stdin);
FILE *fpout = freopen("data.out", "w", stdout);

// input
getchar();
fgetchar();
fgetc(fpin);
scanf("%c", &c);
fgets(s, size, fpin);
gets_s(s, size);
scanf("%s", s);
// output
putchar(c);
fputchar(c);
fputc(c, fpout);
printf("%c", c);
fputs(s, fpout);
puts(s);
printf("%s", s);

fclose(fpin);
fclose(fpout);





/* fopen */
FILE *fin, *fout;
fin = fopen("data.in", "rb");
fout = fopen("data.out", "wb");
// and then we use fscanf and fprintf to read and write
// exp: read from file and write to file
fscanf(fin, "%d", &tmp);
fprintf(fout, "%d", tmp);
// exp: read from keyboard and write to terminal as scanf and printf
fscanf(stdin, "%d", &tmp);
fprintf(stdout, "%d", tmp);
// fscanf(stdin, "%d", &tmp) == scanf("%d", &tmp)
// get and output a char
fscanf(fin, "%c", &c);
c = fgetc(fin);
fprintf(fout, "%c", c);
fputc(c, fout);
// get and output a string
fscanf(fin, "%s", s);
fgets(s, size, fin);
fprintf(fout, "%s", s);
fputs(s, fout);
// EOF: feof(fin);
// after using you need to close stream
fclose(fin);
fclose(fout);





/* input and outpunt exp */
// exp1: we konw the amount of data
typedef long long LL;
const LL SIZE = 1<<8;
int n, arr[SIZE];
scanf("%d", &n);
for (int i = 0; i < SIZE; ++i)
scanf("%d", &arr[i]);
// exp2: we don't know the amount of data and read until EOF
int arr[1<<8];
for (int i = 0; scanf("%d", &arr[i]) == 1; ++i);
// if you want to konw the amount of data
int cnt = 0, arr[1<<8];
for (cnt = 0; scanf("%d", &arr[cnt]) == 1; ++cnt);
// or
int cnt = 0, temp, arr[1<<8];
while (scanf("%d", &temp) == 1)
arr[cnt++] = temp;
// if we want to read char or string from file or your terminal
// from terminal
char str[SIZE], ch;
int cnt = 0;
while ((ch = getchar()) != EOF) str[cnt++] = ch;

while ((str[cnt++] = getchar()) != EOF);
str[cnt-1] = '\0'; // etc

// when you input '#' to end of enter
ch = getchar();
while (ch != '#') {
str[cnt++] = ch;
ch = getchar();
}
// you can use fgetchar() or fgetc(stdin) instead of getchar()
// from file
FILE *fp = fopen("data.in", "rt");
char s[SIZE];
int cnt = 0;
while (!feof(fp)) s[cnt++] = fgetc(fp);
s[cnt-1] = '\0'; // etc





/* output format */
// use sprintf
char format[1<<8];
n = 1 << 4;
sprintf(format, "%s%d%s", "%.", n, "lf");
printf(format, acos(-1.0));
// use *
printf("%.*lf", n, acos(-1.0));





/* Format input(from string) by sscanf */
int day, year;
char weekday[20], month[20], dtm[100];
strcpy( dtm, "Saturday March 25 1989" );
sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year );
// now: weekday-"Saturday" month-"March" day-25 year-1989

1.2.Cplusplus-style

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* standard input and output */
// most C language input and output are supported
// input in C++
cin >> temp;
// output in C++
cout << temp;




/* format */
// use istringstream ostringstream stringstream
stringstream ss;
string s;
ss << s; // put string into stream
ss >> s; // get string from stream
ss.str(""); // clear stream
ss.str(); // return a C++ string

// we can use stringstream for type conversion
stringstream sstream;
int ft, sd;
sstream << "123";
sstream >> ft; // string to int
// if you want to keep converting you need to use clear()
sstream.clear();
sstream << true;
sstream >> sd; // bool to int

int n = atoi(str); // 字符串转整型