火龙信奥
  • 分享
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

第六章 C++ 常用库函数与宏定义

作者: 作者的头像   huolong , 时间:2026-08-20 18:02:59 , 所有人可见, 阅读  38

第六章 C++ 常用库函数与宏定义

在 C++ 中,合理利用标准库提供的函数可以显著提高开发效率并减少出错概率。C++ 的流、容器和算法等都定义在 std 命名空间中,因此在编写程序时,通常需要在 #include 头文件之后引入以下声明:

using namespace std;

本章将详细梳理在信息学奥赛(如 CSP-J、GESP)中常用的库函数,涵盖数组操作、字符处理、数学计算、排序以及随机数生成等核心模块。


6.1 常用库函数详解

1. 数组的整体操作

头文件:<cstring>

在处理数组(特别是邻接矩阵或记忆化数组)时,通常需要对数组进行整体初始化、复制或比较。 * 数组初始化:memset(a, val, sizeof(a)) * 第二个参数 val 传入 0 或 -1 时,数组 a 中的每个元素都会被初始化为 0 或 -1。 * 若传入 0x7F,由于 memset 是按字节进行填充的,数组中每个 4 字节的整型元素将被填充为 0x7F7F7F7F(十进制约为 $2.13 \times 10^9$),在算法竞赛中常用来表示“无穷大”($\infty$)。 * 数据复制:memcpy(b, a, sizeof(a)) * 将数组 a 中的内容整体复制到数组 b 中,需确保 b 空间足够。 * 数组比较:memcmp(a, b, sizeof(a)) * 按字节比较数组 a 和 b 是否等价,若返回 0 则表示完全一致。

2. 字符操作

头文件:<cctype>

用于对单个字符进行类型判断和大小写转换: * tolower(c) / toupper(c):将字符 c 转换为小写 / 大写。 * isdigit(c):判断 c 是否为十进制数字('0'~'9')。 * isalpha(c):判断 c 是否为英文字母(大写或小写)。 * isupper(c) / islower(c):判断 c 是否为大写字母 / 小写字母。 * isgraph(c):判断 c 是否为除空格外的可打印字符。 * isalnum(c):判断 c 是否为字母或数字。

3. 最大值与最小值

头文件:<algorithm>

  • max(a, b):返回 a 和 b 中的较大值。
  • min(a, b):返回 a 和 b 中的较小值。

提示:在简单的数值比较中,也可以通过三目运算符自行实现,如 inline int max(int a, int b) { return a > b ? a : b; }。

4. 交换变量的值

头文件:<algorithm>

  • swap(a, b):交换变量 a 和 b 的值。

在手动实现时,可以使用引用传递:

inline void swap(int &a, int &b) {
    int t = a;
    a = b;
    b = t;
}

5. 排序与反转

头文件:<algorithm>

  • sort(begin, end):将区间 [begin, end) 内的元素按升序排序。
  • sort(begin, end, cmp):使用自定义的比较规则 cmp 进行排序。
  • reverse(begin, end):反转区间 [begin, end) 内的元素顺序。
示例代码:
vector<int> v = {3, 1, 4, 1, 5};
sort(v.begin(), v.end());                 // 升序:v = {1, 1, 3, 4, 5}
sort(v.begin(), v.end(), greater<int>()); // 降序:v = {5, 4, 3, 1, 1}
reverse(v.begin(), v.end());              // 反转:v = {1, 1, 3, 4, 5}

6. 立即退出程序

头文件:<cstdlib>

  • exit(0):强行终止程序运行并返回状态码 0。此函数在深度优先搜索(DFS)中找到最优解需要立刻结束程序时非常实用。在使用前务必先输出计算结果。

7. 运行时间统计

头文件:<ctime>

在算法竞赛中,当程序可能面临运行超时(TLE)风险时,可以使用 clock() 函数获取当前时间,进行“卡时”操作:

double a = (double)clock() / (double)CLOCKS_PER_SEC;

通过在程序关键节点记录时刻并求差,可以精确计算出程序运行的时间间隔。

8. 断言机制

头文件:<cassert>

  • assert(condition):若条件 condition 为假(false),程序会立即崩溃并报错。可以通过在包含头文件前定义 #define NDEBUG 来关闭所有断言。
调试断言与错误处理的区别:
  • 错误处理(如条件限制、输入重新引导)应对的是用户的错误。
  • 断言(assert)应对的是代码的 Bug。如果在计算中途产生了逻辑上绝不可能出现的数据(如人数算出来是负数),应使用断言促使程序崩溃,以便于调试期定位错误源码。

9. 现代随机数发生器

头文件:<random>,<chrono>

竞赛建议:弃用 <cstdlib> 中的 rand() 函数。它的随机数分布不均匀,且最大随机值通常只有 32767,周期较短。

C++11 提供了性能更优异、周期长达 $2^{19937}-1$ 的梅森旋转算法生成器(mt19937):

方案 A(使用高精度系统时间作为种子):
#include <random>
#include <chrono>

// 使用当前高精度时间作为种子
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// 生成 [0, 99] 的均匀整数
uniform_int_distribution<int> dist(0, 99);
int r = dist(rng);

// 生成 [0.0, 1.0) 的均匀浮点数
uniform_real_distribution<double> dist2(0.0, 1.0);
double d = dist2(rng);
方案 B(简化版,秒级种子):
mt19937 rng(time(0));
int r = rng() % 100; // 生成 0~99 之间的整数

提示:time(0) 返回秒级系统时间。如果在同一秒内多次运行该程序,生成的随机序列将会完全相同。在常规竞赛中一般足够使用,若需要更高强度的随机性,建议采用方案 A。

10. 数学函数

头文件:<cmath>

  • abs(x):求整数的绝对值(同时包含于 <cstdlib>,注意与针对浮点数的 fabs 区分)。
  • sin, cos, tan, asin, acos, atan:三角函数及反三角函数,角度单位为弧度。由于 $\tan(\frac{\pi}{4}) = 1$,可以用 acos(-1.0) 或 atan(1) * 4 获得高精度的常数 $\pi$。
  • sinh, cosh, tanh:双曲函数。
  • sqrt(x):计算非负实数 x 的算术平方根。
  • ceil(x) / floor(x):分别向上取整(返回大于等于 x 的最小整数)和向下取整(返回小于等于 x 的最大整数)。注意参数与返回值均为浮点型。
  • exp(x) / log(x) / log10(x):分别求 $e^x$、自然对数 $\ln x$、常用对数 $\lg x$。
  • pow(a, b):计算 $a^b$。由于浮点数存在精度漂移,在需要精确整除的场景下,仍需手写快速幂。
  • fmod(a, b):求浮点数 a / b 的余数。

11. C++17 最大公约数与最小公倍数

头文件:<numeric>

从 C++17 标准开始,标准库提供了内置的 gcd 与 lcm 函数,无需再手动编写欧几里得算法:

#include <numeric>

int g = gcd(12, 18);  // g = 6
int l = lcm(12, 18);  // l = 36

6.2 课后推荐练习题

通过以下题目,可以有效巩固常用库函数(如数学函数、字符处理函数、排序算法等)的使用:

  • 题目编号:11 —— 两点间的距离
    • 考点:本题需要计算笛卡尔坐标系下两点之间的欧几里得距离,适合练习 <cmath> 中 sqrt() 以及乘方运算。
  • 题目编号:42 —— 完整的苹果
    • 考点:计算被虫子咬过的苹果数时,由于不完整的苹果也不能保留,需要结合 <cmath> 中的 ceil() 向上取整函数进行精确计算。
  • 题目编号:92 —— 最大公约数
    • 考点:适合练习手写最大公约数算法,或在 C++17 环境下直接调用 <numeric> 头文件中的 gcd 函数。
  • 题目编号:99 —— 区间排序
    • 考点:练习使用 <algorithm> 中的 sort() 函数对指定数组的特定子区间 [l, r] 进行升序重排。
  • 题目编号:131 —— 最小公倍数
    • 考点:通过最小公倍数与最大公约数的关系 $lcm(a, b) = \frac{a \times b}{gcd(a, b)}$ 来实现计算,可练习 C++17 的 lcm 库函数。
  • 题目编号:136 —— 成绩排序
    • 考点:本题为多关键字排序题,要求对结构体进行多级排序,可深入练习 sort() 函数中自定义比较函数 cmp 的编写。
  • 题目编号:735 —— 统计数字字符的个数
    • 考点:输入一段包含空格的字符串,遍历每个字符,可利用 <cctype> 中的 isdigit() 函数快速统计数字字符的个数。

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

关于火龙

  • 关于我们
  • 学员获奖
  • 预约试听
  • ACM课程
  • CSP课程
  • 学习指南

帮助中心

  • 用户协议
  • 打字练习
  • 在线画图
  • DevC++下载
  • CSP报名
  • GESP官网

推荐课程

  • C++零基础入门(可试看)
  • C++进阶提升
  • GESP考级辅导
  • GESP打卡
  • CSP-J/S打卡

公众号

火龙信奥公众号二维码

地址:义乌市北门街188号新天地商厦二楼2F 邮箱:wdlok305@126.com

© 2017-2026 义乌市睿码科技有限公司版权所有 浙ICP备2021013995号

火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码