机试01——C++基础语法与库函数
一、C++语法基础
- "::“运算符和”:"运算符的区别
:
运算符常见于初始化列表、继承、条件运算符
// 用途一:类继承
class Base {};
class Derived : public Base {}; // 表示Derived继承自Base// 用途二:构造函数初始化列表(相当于对类A的成员变量x传值时,使用A(int val))
class A {int x;
public:A(int val) : x(val) {} // 冒号引出初始化成员变量
};
::
运算符
// 用途一:类外定义成员变量
class A {void func();
};void A::func() {// 这是类A中的成员函数定义
}// 用途二:命名空间中访问成员变量
namespace ns {int x = 42;
}
int y = ns::x; // 使用命名空间作用域解析// 用途三:全局作用域访问
int x = 10;int main() {int x = 20;cout << ::x << endl; // 使用全局的x
}
-
存疑:什么是析构函数
-
类型转换:
- 静态类型转换
静态转换是将一种数据类型的值强制转换为另一种数据类型的值。静态转换通常用于比较类型相似的对象之间的转换,例如将 int 类型转换为 float 类型。静态转换不进行任何运行时类型检查,因此可能会导致运行时错误。
int i = 10;
float f = static_cast<float>(i); // 静态将int类型转换为float类型
- 动态类型转换(常用于向下转型)
class Base {
public:virtual ~Base() {}
};
class Derived : public Base {};Base* p = new Derived();
Derived* d = dynamic_cast<Derived*>(p); // OK,返回实际类型指针Base* p2 = new Base();
Derived* d2 = dynamic_cast<Derived*>(p2); // 转换失败,返回 nullptr
<cmath>库
对数学操作
- 常见函数
三角函数:double cos(double),double sin(double),double tan(double)
对数:double log(double)
次方:pow(double, double)
欧氏距离:hypot(double, double)
平方根:sqrt(double)
- 随机数
#include <iostream>
#include <ctime>
#include <cstdlib>using namespace std;int main ()
{int i,j;// 设置种子srand( (unsigned)time( NULL ) );// 通过时间生成随机种子/* 生成 10 个随机数 */for( i = 0; i < 10; i++ ){// 生成实际的随机数j= rand();cout <<"随机数: " << j << endl;}return 0;
}
- 数字常数
std::numbers::e //自然对数的底数
std::numbers::pi //Π
-
字符串本身的值可以代表这个字符串的首地址
-
时间处理:
#include <iostream>
#include <ctime>
#include <windows.h>
using namespace std;int main() {time_t now = time(0);cout << "1900 到目前经过秒数:" << now << endl;tm* ltm = localtime(&now);cout << 1900 + ltm->tm_year << endl;}
- C++相关的数据结构
- 1.动态数组-
Vector
#include <iostream>
#include <vector>
using namespace std;int main() {// 创建容器vector<int> v;// 1.添加数据v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);// 2.遍历数据for (int num : v) {cout << num << " ";} // 3.访问数据cout << v[0] << endl;cout << v.at(0) << endl;// 4.容器大小cout << v.size() << endl;// 4.删除数据v.erase(v.begin() + 1);// 5.清空数据v.clear();return 0;
}
- 2.数组-Array
int arr[5] = {1, 2, 3, 4, 5};
cout << arr[0]; // 输出第一个元素
固定大小,一旦声明,大小不能改变;
直接访问元素,时间复杂度为 O(1);
适合处理大小已知、元素类型相同的集合。
- 输出固定位数的小数
#include <iostream>
#include <iomanip> // 需要这个头文件
using namespace std;int main() {double num = 3.14159;cout << fixed << setprecision(2) << num << endl; // 输出:3.14return 0;
}
fixed
:以固定小数点格式输出(即非科学计数法)。
setprecision(2)
:控制小数点后保留 2 位。
二、C++常用的库函数
1.<iostream>库:输入输出库
#include <iostream>
#include <iomanip>
using namespace std;int main( )
{string name;string info;//1.输入:cout << "input your name:";cin >> name; //不含空格cout << "input your information:";cin.ignore(); // 清除 cin 中的换行符getline(cin, info); //可以含空格的字符串//2.输出:cout << "name:" << name << endl;cout << "info:" << info << endl;//3.输出两位小数float pi = 3.14159;cout << "Π:" << fixed << setprecision(2) << pi << endl;
}
2.<array>库:数组
#include <iostream>
#include <array>
using namespace std;int main( )
{// 1.数组的创建array<int, 5> arr = {1, 2, 3, 4, 5};// 2.数组元素的访问cout << arr[0] << endl;cout << arr.at(0) << endl; //可以用来检测数组的元素是否越界// 3.数组的大小cout << arr.size() << endl;// 4.访问数组的元素for (int x : arr) {cout << x << " ";}cout << endl;// 5.通过迭代器访问for (auto it = arr.begin(); it != arr.end(); it++) {cout << *it << " ";}// 6.其他方法cout << arr.front() << endl;cout << arr.back() << endl;
}
3.<vector>库:动态数组
#include <iostream>
#include <vector>
using namespace std;int main() {// 创建容器vector<int> v;// 1.添加数据v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);// 2.遍历数据for (int num : v) {cout << num << " ";} // 3.访问数据cout << v[0] << endl;cout << v.at(0) << endl;// 4.容器大小cout << v.size() << endl;// 4.删除数据v.erase(v.begin() + 1);// 5.清空数据v.clear();return 0;
}
- 常用函数
函数 | 说明 |
---|---|
push_back(const T& val) | 在末尾添加元素 |
pop_back() | 删除末尾元素 |
at(size_t pos) | 返回指定位置的元素,带边界检查 |
operator[] | 返回指定位置的元素,不带边界检查 |
front() | 返回第一个元素 |
back() | 返回最后一个元素 |
data() | 返回指向底层数组的指针 |
size() | 返回当前元素数量 |
capacity() | 返回当前分配的容量 |
reserve(size_t n) | 预留至少 n 个元素的存储空间 |
resize(size_t n) | 将元素数量调整为 n |
clear() | 清空所有元素 |
insert(iterator pos, val) | 在指定位置插入元素 |
erase(iterator pos) | 删除指定位置的元素 |
begin() / end() | 返回起始/结束迭代器 |
4.<list>库:双向链表
用于存储元素集合,支持双向迭代器。<list>
是 C++ 标准模板库(STL)中的一个序列容器,它允许在容器的任意位置快速插入和删除元素。
#include <iostream>
#include <list>
using namespace std;int main() {// 1.声明list<string> names;// 2.添加(可前后插入元素)names.push_back("zhangsan");names.push_back("zhangsan1");names.push_back("zhangsan2");names.push_front("zhangsan");names.push_front("zhangsan1");names.push_front("zhangsan2");// 3.访问for(string name : names) {cout << name << " ";}cout << endl;// 4.删除names.pop_back();names.pop_front();auto it = names.begin();advance(it, 2);names.insert(it, "zhangsan0");for (auto it = names.begin(); it != names.end(); ++it) {cout << *it << " ";}cout << endl;// 5.排序/合并/反转/去重list<int> num1 = {1, 6, 2};list<int> num2 = {4, 3, 5, 5};num1.sort();num2.sort();num1.merge(num2);num1.unique();for (auto it = num1.begin(); it != num1.end(); ++it) {cout << *it << " ";}
}
- 常用的函数操作
函数 | 说明 |
---|---|
push_back(const T& val) | 在链表末尾添加元素 |
push_front(const T& val) | 在链表头部添加元素 |
pop_back() | 删除链表末尾的元素 |
pop_front() | 删除链表头部的元素 |
insert(iterator pos, val) | 在指定位置插入元素 |
erase(iterator pos) | 删除指定位置的元素 |
clear() | 清空所有元素 |
size() | 返回链表中的元素数量 |
empty() | 检查链表是否为空 |
front() | 返回链表第一个元素 |
back() | 返回链表最后一个元素 |
remove(const T& val) | 删除所有等于指定值的元素 |
sort() | 对链表中的元素进行排序 |
merge(list& other) | 合并另一个已排序的链表 |
reverse() | 反转链表 |
begin() / end() | 返回链表的起始/结束迭代器 |
TIP:支持随机访问的迭代器(内存是连续的),非随机访问迭代器内存是不连续的
容器类型 | 是否支持 +2 | 备注 |
---|---|---|
std::vector<T> | ✅ 是 | 连续内存,最常见 |
std::deque<T> | ✅ 是 | 虽然内部不是连续的,但支持随机访问 |
std::array<T, N> | ✅ 是 | 固定大小数组 |
C 风格数组 T arr[N] | ✅ 是 | 本质上是指针操作 |
std::string | ✅ 是 | 本质上是 basic_string<char> ,支持随机访问 |
容器类型 | 是否支持 +2 | 迭代器类型 | 替代方案 |
---|---|---|---|
std::list<T> | ❌ 否 | 双向迭代器 | 使用 std::advance(it, n) |
std::forward_list<T> | ❌ 否 | 单向(前向)迭代器 | 只能前向 advance |
std::set<T> | ❌ 否 | 双向迭代器 | 用 advance() |
std::map<K, V> | ❌ 否 | 双向迭代器 | 同上 |
std::unordered_set<T> | ❌ 否 | 单向迭代器 | 用循环前进 |
std::unordered_map<K, V> | ❌ 否 | 单向迭代器 | 同上 |
5. <deque>库:双向队列
双端队列是一种允许在两端进行插入和删除操作的线性数据结构。
<deque>
是一个动态数组,它提供了快速的随机访问能力,同时允许在两端进行高效的插入和删除操作。这使得 <deque>
成为处理需要频繁插入和删除元素的场景的理想选择。
#include <iostream>
#include <deque>int main() {std::deque<int> myDeque;// 插入元素myDeque.push_back(10);myDeque.push_back(20);myDeque.push_front(5);// 访问元素std::cout << "Deque contains: ";for (int i = 0; i < myDeque.size(); ++i) {std::cout << myDeque[i] << " ";}std::cout << std::endl;// 删除元素myDeque.pop_back();myDeque.pop_front();// 再次访问元素std::cout << "Deque after popping: ";for (int i = 0; i < myDeque.size(); ++i) {std::cout << myDeque[i] << " ";}std::cout << std::endl;return 0;
}
6.<stack>库:栈
<stack>
是 C++ 标准模板库(STL)的一部分,它实现了一个后进先出(LIFO,Last In First Out)的数据结构。这种数据结构非常适合于需要"最后添加的元素最先被移除"的场景。
push()
: 在栈顶添加一个元素。pop()
: 移除栈顶元素。top()
: 返回栈顶元素的引用,但不移除它。empty()
: 检查栈是否为空。size()
: 返回栈中元素的数量。
#include <iostream>
#include <stack>int main() {std::stack<int> s;// 向栈中添加元素s.push(1);s.push(2);s.push(3);// 访问栈顶元素std::cout << "Top element is: " << s.top() << std::endl;// 移除栈顶元素s.pop();std::cout << "After popping, top element is: " << s.top() << std::endl;// 检查栈是否为空if (!s.empty()) {std::cout << "Stack is not empty." << std::endl;}// 打印栈的大小std::cout << "Size of stack: " << s.size() << std::endl;return 0;
}
7.<queue>库:队列
empty()
: 检查队列是否为空。size()
: 返回队列中的元素数量。front()
: 返回队首元素的引用。back()
: 返回队尾元素的引用。push()
: 在队尾添加一个元素。pop()
: 移除队首元素。
#include <iostream>
#include <queue>int main() {// 创建一个整数队列std::queue<int> q;// 向队列中添加元素q.push(10);q.push(20);q.push(30);// 打印队列中的元素数量std::cout << "队列中的元素数量: " << q.size() << std::endl;// 打印队首元素std::cout << "队首元素: " << q.front() << std::endl;// 打印队尾元素std::cout << "队尾元素: " << q.back() << std::endl;// 移除队首元素q.pop();std::cout << "移除队首元素后,队首元素: " << q.front() << std::endl;// 再次打印队列中的元素数量std::cout << "队列中的元素数量: " << q.size() << std::endl;return 0;
}
8.<priority_queue>库:优先队列(大小顶堆)
empty()
: 检查队列是否为空。size()
: 返回队列中的元素数量。top()
: 返回队列顶部的元素(不删除它)。push()
: 向队列添加一个元素。pop()
: 移除队列顶部的元素。
<Node, std::vector<Node>, std::greater<Node>>
:
位置 | 含义 | 示例含义(以 Node 为例) |
---|---|---|
第1项 | 存储的数据类型 | Node 表示优先队列中的元素类型 |
第2项 | 底层容器类型 | std::vector<Node> 是内部实际存储结构 |
第3项 | 比较函数对象(排序方式) | std::greater<Node> 表示使用“小顶堆”逻辑比较 |
#include <iostream>
#include <queue>
#include <vector>using namespace std;struct compare {bool operator()(int a, int b) {return a > b;}
};int main() {// 1.定义一个大顶堆(默认)priority_queue<int> qp;qp.push(1);qp.push(3);qp.push(2);while (!qp.empty()) {cout << qp.top() << endl;qp.pop();}// 2.自定义优先级(举例:小顶堆)priority_queue<int, vector<int>, compare> qp_min;qp_min.push(1);qp_min.push(3);qp_min.push(2);while (!qp_min.empty()) {cout << qp_min.top() << endl;qp_min.pop();}
}
9.<set>库:集合
C++ 标准库中的 <set>
是一个关联容器,它存储了一组唯一的元素,并按照一定的顺序进行排序。
<set>
提供了高效的元素查找、插入和删除操作。它是基于红黑树实现的,因此具有对数时间复杂度的查找、插入和删除性能。
要求:
<set>
容器中存储的元素类型必须满足以下条件:
- 元素类型必须可以比较大小。
- 元素类型必须可以被复制和赋值。
操作:
insert(元素)
: 插入一个元素。erase(元素)
: 删除一个元素。find(元素)
: 查找一个元素。size()
: 返回容器中元素的数量。empty()
: 检查容器是否为空。
#include <iostream>
#include <set>using namespace std;
int main() {//1.创建集合set<int> s;//2.插入集合元素s.insert(5);s.insert(2);s.insert(4);s.insert(4);s.insert(6);//3.遍历集合元素for(int num : s) {cout << num << " ";}cout << endl;//4.删除元素s.erase(5);for(int num : s) {cout << num << " ";}cout << endl;//5.查找元素(返回一个迭代器)cout << *s.find(4) << endl;if (s.find(6) != s.end()) {cout << "set存在该元素" << endl;} else {cout << "set中不存在该元素" << endl;}
}
10.<map>库:键值对
- 键值对:
map
存储的是键值对,其中每个键都是唯一的。 - 排序:
map
中的元素按照键的顺序自动排序,通常是升序。 - 唯一性:每个键在
map
中只能出现一次。 - 双向迭代器:
map
提供了双向迭代器,可以向前和向后遍历元素。
#include <iostream>
#include <map>
using namespace std;int main() {//声明map容器map<int, string> mymap;map<int, string> mymap1 = {{1, "xyx"}, {2, "yhw"}};//插入map元素mymap[0] = "zhangsan0";mymap[1] = "zhangsan1";mymap[2] = "zhangsan2";mymap[3] = "zhangsan3";//查看map元素for(auto name : mymap) {cout << name.first << "=>" << name.second << endl;}for(auto name : mymap1) {cout << name.first << "=>" << name.second << endl;}//查找元素的值(返回迭代器)cout << mymap.find(1)->first << mymap.find(1)->second << endl;
}
11.<algorithm>库:常用算法库
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>using namespace std;bool compare(int a, int b) {return a > b;
}int main() {//1.排序//模板:sort(container.begin(), container.end(), compare_function);vector<int> v = {1, 3, 2, 4, 6, 5};sort(v.begin(), v.end(), compare);for (int num : v) {cout << num << endl;}//模板:按照下一个字典序排列(1,2,3)-> (1, 3, 2) //2.查找//模板:auto it = find(container.begin(), container.end(), value);if (find(v.begin(), v.end(), 5) != v.end()) {cout << "Found" << endl;} else {cout << "Not Found" << endl;}//3.复制//模板:copy(source_begin, source_end, destination_begin);vector<int> v1 = {1, 3, 2, 4, 3, 6};set<int> s;copy(v1.begin(), v1.end(), inserter(s, s.begin()));for (int num : s) {cout << num << " ";}cout << endl;//4.比较(比较两个容器或两个范围内的元素是否相等)//模板:bool result = equal(first1, last1, first2, compare_function);vector<int> v3 = {1, 2, 3};vector<int> v4 = {1, 2, 3, 4};bool res = equal(v4.begin(), v4.end() - 1, v3.begin());cout << res << endl;//5.反转算法//模板:std::reverse(vec.begin(), vec.end());vector<int> v5 = {1, 2, 3, 4};reverse(v5.begin(), v5.end());for (int num : v5) {cout << num << " ";}cout << endl;//6.填充/代替//模板:std::fill(vec.begin(), vec.end(), value); // 所有元素设为value//模板:std::replace(vec.begin(), vec.end(), 原始, 替换);fill(v.begin(), v.end(), 1);replace(v.begin(), v.end(), 1, 100);for (int num : v) {cout << num << " ";}cout << endl;//7.合并(将两个有序区间合并到一个有序区间)//模板:std::merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());vector<int> v6 = {1, 3, 5};vector<int> v7 = {2, 4, 6};vector<int> result(6);merge(v6.begin(), v6.end(), v7.begin(), v7.end(), result.begin());for (int num : result) {cout << num << " ";}cout << endl;//8.集合运算set<int> set1 = {1, 2, 3, 4, 5};set<int> set2 = {2, 4, 6};vector<int> set3(6);//并set_union(set1.begin(), set1.end(), set2.begin(), set2.end(), set3.begin());for (int num : set1) {cout << num << " ";}cout << endl;//交set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), set3.begin());for (int num : set2) {cout << num << " ";}cout << endl;//差set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), set3.begin());for (int num : set3) {cout << num << " ";}cout << endl;
}