青江的个人站

“保持热爱,奔赴星海”

  • 主页
  • 目录
  • 图床
  • 留言板
  • -关于我-
友链 搜索文章 >>

青江的个人站

“保持热爱,奔赴星海”

  • 主页
  • 目录
  • 图床
  • 留言板
  • -关于我-

【C语言学习笔记】十二、常用库函数(数学、时间与错误处理)


阅读数: 0次    2026-02-10
字数:3.2k字 | 预计阅读时长:14分钟

1. 章节概述

本章主要对一些常用的库函数做介绍,包括数学库、时间库与错误处理库。

其中数学库可能会在科研计算中用到,包含各种常见曲线与函数。

时间库函数包含时间戳的使用,比较重要。

错误处理库在前面一些章节中已经有所涉及。

2. 三角函数与M_PI

M_PI代表数学中的“π”,想要使用类似的数学符号,需要在包含<math.h>之前定义_USE_MATH_DEFINES,用于在MSVC中启用数学常量定义。

计算三角函数可以直接调用对应函数。

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
#include <stdio.h>
#define _USE_MATH_DEFINES // 在MSVC中启用数学常量定义
#include <math.h>

// 三角函数
int main() {
double input_angle_degrees = 0.0;
double input_angle_radians = 0.0;

printf("请输入一个角度(单位:度):");
scanf_s("%lf", &input_angle_degrees);

// 将角度转换为弧度
input_angle_radians = input_angle_degrees * (M_PI / 180.0);

// 计算正弦值
double sine_value = sin(input_angle_radians);
printf("角度 %.2f 度的正弦值为: %.4f\n", input_angle_degrees, sine_value);

// 计算余弦值
double cosine_value = cos(input_angle_radians);
printf("角度 %.2f 度的余弦值为: %.4f\n", input_angle_degrees, cosine_value);

// 计算正切值
double tangent_value = tan(input_angle_radians);
printf("角度 %.2f 度的正切值为: %.4f\n", input_angle_degrees, tangent_value);

// 计算反正弦值
double arcsine_value = asin(sine_value) * (180.0 / M_PI);
printf("正弦值 %.4f 的反正弦值为: %.2f 度\n", sine_value, arcsine_value);

// 计算反余弦值
double arccosine_value = acos(cosine_value) * (180.0 / M_PI);
printf("余弦值 %.4f 的反余弦值为: %.2f 度\n", cosine_value, arccosine_value);

// 计算反正切值
double arctangent_value = atan(tangent_value) * (180.0 / M_PI);
printf("正切值 %.4f 的反正切值为: %.2f 度\n", tangent_value, arctangent_value);

return 0;
}

3. 双曲函数

计算双曲函数可以直接调用对应函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#define _USE_MATH_DEFINES // 在MSVC中启用数学常量定义
#include <math.h>

// 双曲函数
int main() {
double input_value = 1.0;

// 计算双曲正弦值
double sinh_value = sinh(input_value);
printf("sinh(%.2f) = %.6f\n", input_value, sinh_value);

// 计算双曲余弦值
double cosh_value = cosh(input_value);
printf("cosh(%.2f) = %.6f\n", input_value, cosh_value);

// 计算双曲正切值
double tanh_value = tanh(input_value);
printf("tanh(%.2f) = %.6f\n", input_value, tanh_value);

return 0;
}

4. 指数和对数

计算指数和对数值可以直接调用对应函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#define _USE_MATH_DEFINES // 在MSVC中启用数学常量定义
#include <math.h>

// 指数和对数
int main() {
double input_exp = 1.0; // 指数函数的输入
double input_log = 2.71828; // 对数函数的输入,接近e
double input_log10 = 100.0; // 以10为底的对数函数的输入

// 计算指数函数
double result_exp = exp(input_exp);
printf("exp(%.2f) = %.5f\n", input_exp, result_exp);

// 计算自然对数函数
double result_log = log(input_log);
printf("log(%.5f) = %.5f\n", input_log, result_log);

// 计算以10为底的对数函数
double result_log10 = log10(input_log10);
printf("log10(%.2f) = %.5f\n", input_log10, result_log10);

return 0;
}

5. 常见math类别函数汇总

本节介绍一些常见的数学函数,包括求平方根、绝对值、向上取整、向下取整、取余。

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
#include <stdio.h>
#define _USE_MATH_DEFINES // 在MSVC中启用数学常量定义
#include <math.h>

int main() {
double num_sqrt = 16.0; // 用于计算平方根的数字
double num_fabs = -5.5; // 用于计算绝对值的数字
double num_ceil = 4.3; // 用于向上取整的数字
double num_floor = 4.7; // 用于向下取整的数字
double num_fmod1 = 5.3; // 用于取余的第一个数字
double num_fmod2 = 2.0; // 用于取余的第二个数字

// 计算平方根
double result_sqrt = sqrt(num_sqrt);
printf("The square root of %.2f is %.2f\n", num_sqrt, result_sqrt);

// 计算绝对值
double result_fabs = fabs(num_fabs);
printf("The absolute value of %.2f is %.2f\n", num_fabs, result_fabs);

// 向上取整
double result_ceil = ceil(num_ceil);
printf("The ceiling of %.2f is %.2f\n", num_ceil, result_ceil);

// 向下取整
double result_floor = floor(num_floor);
printf("The floor of %.2f is %.2f\n", num_floor, result_floor);

// 计算取余
double result_fmod = fmod(num_fmod1, num_fmod2);
printf("The remainder of %.2f divided by %.2f is %.2f\n", num_fmod1, num_fmod2, result_fmod);

return 0;
}

6. pow幂函数

传入两个参数,例如result = pow(a, b),相当于result=abresult = a ^ bresult=ab。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#define _USE_MATH_DEFINES // 在MSVC中启用数学常量定义
#include <math.h>

// 幂函数
int main() {
// 计算圆的面积
double radius = 5.0;
double area = M_PI * pow(radius, 2);
printf("Radius: %.2f, Area: %.2f\n", radius, area);

// 计算正方形的面积
double side = 4.0;
double square_area = pow(side, 2);
printf("Side: %.2f, Square Area: %.2f\n", side, square_area);

return 0;
}

7. 对于math类别的错误处理:EDOM、ERANGE、HUGE_VAL

如果想要使用不安全的函数,例如scanf,可以在头文件之前添加一个定义:

1
#define _CRT_SECURE_NO_WARNINGS	// 禁用不安全函数警告

但不建议这样处理,可能会导致内存问题。

可以引入头文件errno.h用于错误处理。

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
#include <stdio.h>
#include <math.h>
#include <errno.h>

int main(void) {
double number = 0.0; // 用户输入的数字
double result = 0.0; // 计算结果

printf("请输入一个数字以计算其平方根: ");
scanf_s("%lf", &number);

errno = 0; // 重置errno以检测错误

result = sqrt(number); // 计算平方根

// 检查是否发生了错误
if (errno == EDOM) { // 输入的数字为负数
printf("错误: 输入的数字不能为负数。\n");
}
else if (errno == ERANGE) { // 输入的数字过大
printf("错误: 输入的数字过大,无法计算平方根。\n");
}
else if (errno == HUGE_VAL) { // 计算结果过大
printf("错误: 计算结果过大,无法表示。\n");
}
else { // 没有错误,输出结果
printf("数字 %.2lf 的平方根是 %.2lf\n", number, result);

}

return 0;
}

8. 检查浮点数类别与属性

fpclassify函数可以检查传入的浮点数的类别,返回一些特殊的宏定义值。

其他的一些函数可以检查传入的浮点数的属性,具体用法可以参考下面的示例。

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
#include <stdio.h>
#include <math.h>

// 检查浮点数的分类
void check_float(double number);

int main(void) {
double numbers[] = { 0.0, -0.0, 1.0, -1.0, INFINITY, -INFINITY, NAN };
for (int i = 0; i < sizeof(numbers) / sizeof(numbers[0]); i++) {
check_float(numbers[i]);
}

return 0;
}

// 检查浮点数的分类
void check_float(double number) {
// 使用 fpclassify 函数检查浮点数的分类
switch (fpclassify(number)) {
case FP_INFINITE:
printf("%.2lf 是无穷大\n", number);
break;
case FP_NAN:
printf("%.2lf 是非数\n", number);
break;
case FP_NORMAL:
printf("%.2lf 是正常数\n", number);
break;
case FP_SUBNORMAL:
printf("%.2lf 是次正规数\n", number);
break;
case FP_ZERO:
printf("%.2lf 是零\n", number);
break;
default:
printf("%.2lf 的分类未知\n", number);
break;
}
// 检查是否为有限数
if (isfinite(number)) {
printf("%.2lf 是有限数\n", number);
}
// 检查是否为无穷大
if (isinf(number)) {
printf("%.2lf 是无穷大\n", number);
}
// 检查是否为非数
if (isnan(number)) {
printf("%.2lf 是非数\n", number);
}
// 检查是否为正常数
if (isnormal(number)) {
printf("%.2lf 是正常数\n", number);
}
// 检查符号
if (signbit(number)) {
printf("%.2lf 是负数\n", number);
}
else {
printf("%.2lf 是正数或零\n", number);
}
printf("\n");
}

9. 浮点数的比较与差值

fmax:返回传入的两个浮点数中的较大值。

fmin:返回传入的两个浮点数中的较小值。

fdim:用于计算传入的两个浮点数之间的正差值。如果第一个参数xxx大于第二个参数yyy(x>yx > yx>y),返回x−yx - yx−y;如果x≤yx \leq yx≤y,则返回0.0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
double number_1 = 5.8;
double number_2 = 7.2;
double number_3 = 3.1;

// 得出两数的较大值
double max = fmax(number_1, number_2);
printf("The maximum of %.2lf and %.2lf is %.2lf\n", number_1, number_2, max);

// 得出两数的较小值
double min = fmin(number_1, number_2);
printf("The minimum of %.2lf and %.2lf is %.2lf\n", number_1, number_2, min);

// 得出两数的差值
double diff_1 = fdim(number_1, number_2);
printf("The difference between %.2lf and %.2lf is %.2lf\n", number_1, number_2, diff_1);

double diff_2 = fdim(number_2, number_3);
printf("The difference between %.2lf and %.2lf is %.2lf\n", number_2, number_3, diff_2);

10. 舍入和剩余函数

函数的用法与效果参考示例。

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
double value = 2.845;
double divisor = 2.0;

printf("=== 舍入函数示例 (value = %.3f) ===\n\n", value);

// round 系列:四舍五入到最接近的整数(0.5 向远离 0 的方向舍入)
printf("round(%f) = %f\n", value, round(value)); // 返回 double 类型
printf("lround(%f) = %ld\n", value, lround(value)); // 返回 long 类型
printf("llround(%f) = %lld\n\n", value, llround(value)); // 返回 long long 类型

// rint 系列:根据当前舍入模式舍入(默认为四舍六入五取偶)
printf("rint(%f) = %f\n", value, rint(value)); // 返回 double 类型
printf("lrint(%f) = %ld\n", value, lrint(value)); // 返回 long 类型
printf("llrint(%f) = %lld\n\n", value, llrint(value)); // 返回 long long 类型

// nearbyint:与 rint 类似,但不会触发浮点异常
printf("nearbyint(%f) = %f\n\n", value, nearbyint(value));

// 余数函数:计算 IEEE 余数(结果符号可能与被除数不同)
printf("=== 余数函数示例 ===\n");
printf("remainder(%.3f, %.1f) = %f\n", value, divisor, remainder(value, divisor));
printf("(IEEE 余数,结果范围:[-%.1f, %.1f])\n\n", divisor/2, divisor/2);

// 特殊情况:展示 0.5 时不同舍入函数的行为差异
printf("=== 特殊情况:0.5 的舍入行为 ===\n");
double special_value = 2.5;
printf("round(%.1f) = %.1f // 四舍五入:0.5 向远离 0 方向\n", special_value, round(special_value));
printf("rint(%.1f) = %.1f // 银行家舍入:0.5 取最近的偶数\n", special_value, rint(special_value));
printf("nearbyint(%.1f) = %.1f // 同 rint,但不触发异常\n", special_value, nearbyint(special_value));

11. time.h与时间戳的使用

时间戳:时间戳记或称为时间标记(timestamp),是指字符串或编码信息用于识别记录下来的时间日期。

time.h头文件提供了处理和操作日期和时间的函数和类型。

部分函数的使用方法参考下面的示例。

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
#include <stdio.h>
#include <time.h>

int main(void) {
/*
* time() - 获取当前日历时间
* 返回值: 当前时间戳(自 1970-01-01 00:00:00 UTC 的秒数),失败返回 -1
*/
time_t current_time = time(NULL);
if (current_time == -1) {
perror("Failed to get current time");
return 1;
}
printf("Current time (time_t): %lld\n\n", (long long)current_time);

/*
* === 本地时间处理 ===
* localtime_s() - 将 time_t 转换为本地时区的 struct tm 结构
* struct tm 包含: tm_year(年), tm_mon(月 0-11), tm_mday(日), tm_hour(时),
* tm_min(分), tm_sec(秒), tm_wday(星期 0-6), tm_yday(年中天数)
*/
struct tm local_time;
localtime_s(&local_time, &current_time);

/*
* strftime() - 格式化时间字符串
* 常用格式符: %Y(年) %m(月) %d(日) %H(时) %M(分) %S(秒) %A(星期) %B(月份名)
*/
char local_time_str[100];
strftime(local_time_str, sizeof(local_time_str), "%Y-%m-%d %H:%M:%S", &local_time);
printf("Local time: %s\n", local_time_str);

/*
* === UTC 时间处理 ===
* gmtime_s() - 将 time_t 转换为 UTC 时间(不考虑本地时区)
*/
struct tm utc_time;
gmtime_s(&utc_time, &current_time);

char utc_time_str[100];
strftime(utc_time_str, sizeof(utc_time_str), "%Y-%m-%d %H:%M:%S", &utc_time);
printf("UTC time: %s\n", utc_time_str);

// 显示本地时间与 UTC 的时区差异(单位:小时)
printf("\n时区差异: %d 小时\n", local_time.tm_hour - utc_time.tm_hour);

return 0;
}

12. 简单回顾错误处理函数

errno.h头文件提供了一种在程序中报告和处理错误的机制。这个头文件定义了宏和变量,用于指示和描述运行时错误的类型。

错误处理常见的函数有perror与strerror_s,可以打印出最后发生的错误类型及相关信息,使用方法可以参考上一章节文件中的部分示例。

下面是一个简单的错误处理示例,以供参考。

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
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void) {
FILE* file;
errno_t err;
char errMsg[256];

printf("=== C语言错误处理示例 ===\n\n");

// 示例1: 使用 perror() 函数
printf("1. 使用 perror() 函数:\n");
err = fopen_s(&file, "不存在的文件.txt", "r");
if (err != 0) {
perror(" 错误");
}

printf("\n");

// 示例2: 使用 strerror_s() 函数
printf("2. 使用 strerror_s() 函数:\n");
err = fopen_s(&file, "another_nonexistent_file.txt", "r");
if (err != 0) {
strerror_s(errMsg, sizeof(errMsg), err);
printf(" 打开文件失败: %s\n", errMsg);
printf(" 错误代码: %d\n", err);
}

printf("\n");

// 示例3: 自定义错误消息
printf("3. 自定义错误消息:\n");
err = fopen_s(&file, "test.txt", "r");
if (err != 0) {
strerror_s(errMsg, sizeof(errMsg), err);
fprintf(stderr, " 无法打开文件 'test.txt': %s (errno=%d)\n",
errMsg, err);
}

printf("\n");

// 示例4: 成功的操作
printf("4. 成功操作示例:\n");
err = fopen_s(&file, "main.c", "r");
if (err == 0) {
printf(" 成功打开 main.c 文件!\n");
fclose(file);
}
else {
perror(" 打开 main.c 失败");
}

return 0;
}

13. 第十二章结束语

至此,常见的库函数已经基本上介绍完毕。

其他的库函数可以在用到的时候自行搜索了解学习。

本文来源: 青江的个人站
本文链接: https://hanqingjiang.com/2026/02/10/20260210_C_common_libs/
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
知识共享许可协议
赏

谢谢你请我喝可乐~

支付宝
微信
  • Notes
  • C

扫一扫,分享到微信

微信分享二维码
【C语言学习笔记】十一、文件
  1. 1. 1. 章节概述
  2. 2. 2. 三角函数与M_PI
  3. 3. 3. 双曲函数
  4. 4. 4. 指数和对数
  5. 5. 5. 常见math类别函数汇总
  6. 6. 6. pow幂函数
  7. 7. 7. 对于math类别的错误处理:EDOM、ERANGE、HUGE_VAL
  8. 8. 8. 检查浮点数类别与属性
  9. 9. 9. 浮点数的比较与差值
  10. 10. 10. 舍入和剩余函数
  11. 11. 11. time.h与时间戳的使用
  12. 12. 12. 简单回顾错误处理函数
  13. 13. 13. 第十二章结束语
© 2021-2026 青江的个人站
晋ICP备2024051277号-1
powered by Hexo & Yilia
  • 友链
  • 搜索文章 >>

tag:

  • 生日快乐🎂
  • 新年快乐!
  • 小技巧
  • Linux
  • 命令
  • 语录
  • 复刻
  • Blog
  • Notes
  • Android
  • C
  • FPGA
  • Homework
  • MATLAB
  • Server
  • Vivado
  • Git

  • 引路人-稚晖
  • Bilibili-稚晖君
  • 超有趣讲师-Frank
  • Bilibili-Frank