cpp-cramming
cpp-cramming
Created: 2023-08-27T11:52+08:00
本文旨在迅速了解 CPP 提供的 STL api 以应付考试。
头文件
头文件很重要:
#include <iostream> // io 流 #include <cstring> // 处理 char*风格的字符串 #include <vector> #include <stack> #include <map> // 基于红黑树 #include <set> // 基于红黑树 #include <unordered_map> // 哈希表 #include <unordered_set> // 基于哈希的 set #include <cmath> #include <algorithm> using namespace std;
输入输出
输入输出使用的头文件为 <iostream>
,更为推荐的是使用 printf
和 scanf
,因为 cin
和 cout
太慢了,这里只做介绍。
使用下面的语句可以让 cin cout 变快,参考sync_with_stdio 和 cin.tie(0); cout.tie(0);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
读取输入的整数/小数
在保证以空白符分割的情况下,cin >> a
,就是读入一个数到 a 里。cin >> a >> b >> c
,逐个读入。
#include<iostream> using namespace std; int main() { int i_var; double d_var; cin >> i_var >> d_var; cout << "input int number is " << i_var << endl; cout << "input double number is " << d_var << endl; return 0; }
很智能,可以自动转换输入的字符串为数字类型。以下是一个样例:
1 1234.66788 input int number is 1 input double number is 1234.67 -------------------------------- Process exited after 5.21 seconds with return value 0 请按任意键继续. .
读取输入的字符串
字符串使用 char[]
存储,而不是通过 <string>
使用 cpp 的类,否则会慢。
关于 <cstring>
和 <string>
的区别,见difference between cstring and string。
Well,
<cstring>
is basically a header containing a set of functions for dealing with C-style strings (char*).<string>
, on the other hand, is header that allows you to use C++-style strings (std::string), which can do a lot of if not all of the functions provided in<cstring>
on their own.
直接使用 cin 流,只能拿到空格分割的字符串。
#include<iostream> using namespace std; int main() { char s1[20] = {0}; char s2[20] = {0}; cin >> s1 >> s2; cout << "s1: " << s1 << endl; cout << "s2: " << s2 << endl; return 0; }
以下是一个样例,可见输入的字符串被空白符分割了。
hhh 11 445 s1: hhh s2: 11 -------------------------------- Process exited after 4.601 seconds with return value 0 请按任意键继续. . .
使用 gets(s)
就能获取一行的输入,这就是 c 的范畴了。
使用 scanf 读取 string
如果一定要使用 scanf,则需要为 string 预留空间。并且是 &s[0]
而不是 &a
。
//#include <algorithm> #include <iostream> using namespace std; int main() { string a; a.resize(3); scanf("%s", &a[0]); cout << a << endl; return 0; }
algorithm
std::swap
可以交换两个元素
#include <algorithm> #include <iostream> using namespace std; int main() { int a[2] = {0,1}; cout << "before swap\n"; cout << a[0] << endl << a[1] << endl; swap(a[0], a[1]); cout << "after swap\n"; cout << a[0] << endl << a[1] << endl; return 0; }
container
- stack
- vector
有一些函数是重复的:
size()
返回容器的大小
empty()
:就是 .size()==0?
erase(key/iterator)
: 删除对应的元素
insert()
: 插入元素
emplace()
: 不做要求,毕竟是 cram,放一个 element 进去。
vector
- 增:
v.push_back(value)
: 加到最后v.insert(iter, value)
: 插入到 iter 前
- 删除:
v.erase(iter)
: 移除对应迭代器位置的元素,返回移除后下一个元素的迭代器v.pop_back()
: 删除最后一个元素v.clear()
: 删除所有元素- 迭代删除:如果要删除所有值为 value 的元素,使用
it = v.erase(it)
- 改:
v[idx] = newValue
*iter = newValue
- 查:没有提供
find()
接口,自己迭代查。
int main(void) { vector<int> v; v.push_back(1); // {1} v.insert(v.begin(), 0); // {0, 1} v.erase(v.begin()); // {1} v[0] = 2; // {2} // 展示 erase 用法 v = { 1, 2, 3, 3, 3, 4, 3 }; for (auto& i : v) std::cout << i << std::endl; for (auto it = v.begin(); it != v.end();) { if (*it == 3) { it = v.erase(it); } else { ++it; } } std::cout << "after erase" << std::endl; for (auto& i : v) std::cout << i << std::endl; }
stack
我写的第一行 stack 代码:
stack s = {1,2,3}
随手一写,三个错误,cpp 有多牛就不必多说了
正确的写法:stack<int> s({1,2,3});
top()
: 返回栈顶元素的引用
pop()
: 弹出栈顶元素
int main() { pair<int, int> a={1,2}; vector<int> vec_a = {1,2,3}; vec_a.push_back(4); unordered_map<string, int> votes; pair<string, int> p = {"Alice", 5}; votes.insert(p); cout << a.second << endl; cout << vec_a[0] << endl; cout << votes["Alice"] << endl; return 0; }
unordered_map
基于哈希实现的 map
- 增加:直接
m[key] = value
- 删除:
m.erase(key)
- 修改:
m[key] = newValue
- 查找:用于判断 key 是否存在于 map 中,三种方法
m.count(key) > 0
m.find(key) != m.end()
m.contains(key)
,注意只能在 c++20 或以上版本使用
int main(void) { // 初始化 unordered_map<string, int> strCnt = { { "hello", 2 }, { "world", 3 } }; // 遍历 for (auto& p : strCnt) { std::cout << p.first << p.second << std::endl; } // 增加一个 new <key, value> string s = "life"; strCnt["life"] = 4; std::cout << strCnt[s] << std::endl; // 4 // 使用 erase(key) 删除 strCnt.erase("world"); std::cout << strCnt.size() << std::endl; // 2 // 直接修改 strCnt["hello"] = 1; // cover original value std::cout << strCnt["hello"] << std::endl; // 1 // 查找 std::cout << strCnt.count("hello") << std::endl; // 1 std::cout << strCnt.count("world") << std::endl; // 0 // std::cout << strCnt.contains("hello") << std::endl; // available in c++20 std::cout << (strCnt.find("hello") != strCnt.end()) << std::endl; // 1 return 0; }
unordered_set
- 增:
s.insert(value)
- 查:
s.find(value)
,返回对应的 iter,通过s.find(value) != s.end()
判断找到了元素 - 删:
s.erase(it)
- 改:没法改,删了再改
int main(void) { std::unordered_set<int> ages; ages.insert(10); ages.insert(12); ages.insert(11); for (auto & i: ages) { std::cout << i << std::endl; } auto it = ages.find(10); ages.erase(it); }
set
set
和 unordered_set
使用场景的区别就是,是否需要保证存储的 key 是有序的。比如存储身高,最后要求升序输出所有存储好的身高。
内部实现是红黑树,所以查找的复杂度是
int main(void) { std::set<int> ages; ages.insert(10); ages.insert(12); ages.insert(11); for (auto & i: ages) { // 将观察到有序输出 std::cout << i << std::endl; } auto it = ages.find(10); ages.erase(it); }
如果您有任何关于文章的建议,欢迎评论或在 GitHub 提 PR
作者:dutrmp19
本文为作者原创,转载请在 文章开头 注明出处:https://www.cnblogs.com/dutrmp19/p/15681375.html
遵循 CC 4.0 BY-SA 版权协议
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本