跳到主要内容

标准库

C 标准库提供了大量实用函数,涵盖输入输出、字符串处理、数学计算、内存管理等方面。熟练使用标准库可以大大提高开发效率。

输入输出库 stdio.h

文件操作

FILE* fopen(const char* filename, const char* mode);  // 打开文件
int fclose(FILE* stream); // 关闭文件
int fflush(FILE* stream); // 刷新缓冲区

格式化输入输出

int printf(const char* format, ...);      // 格式化输出到 stdout
int fprintf(FILE* stream, const char* format, ...); // 格式化输出到文件
int sprintf(char* str, const char* format, ...); // 格式化输出到字符串
int snprintf(char* str, size_t size, const char* format, ...); // 安全版本

int scanf(const char* format, ...); // 从 stdin 格式化输入
int fscanf(FILE* stream, const char* format, ...); // 从文件格式化输入
int sscanf(const char* str, const char* format, ...); // 从字符串格式化输入

格式说明符:

格式符说明
%d有符号十进制整数
%u无符号十进制整数
%x十六进制(小写)
%X十六进制(大写)
%o八进制
%f浮点数
%e科学计数法
%c字符
%s字符串
%p指针
%zusize_t
%%百分号

字符输入输出

int fgetc(FILE* stream);              // 从文件读取一个字符
int fputc(int ch, FILE* stream); // 向文件写入一个字符
char* fgets(char* str, int n, FILE* stream); // 从文件读取一行
int fputs(const char* str, FILE* stream); // 向文件写入字符串

二进制输入输出

size_t fread(void* ptr, size_t size, size_t count, FILE* stream);
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);

文件定位

int fseek(FILE* stream, long offset, int origin);  // 设置文件位置
long ftell(FILE* stream); // 获取文件位置
void rewind(FILE* stream); // 重置到开头
int feof(FILE* stream); // 检查是否到达末尾

标准库 stdlib.h

内存管理

void* malloc(size_t size);           // 分配内存
void* calloc(size_t n, size_t size); // 分配并初始化为 0
void* realloc(void* ptr, size_t size); // 重新分配
void free(void* ptr); // 释放内存

字符串转换

int atoi(const char* str);           // 字符串转整数
long atol(const char* str); // 字符串转 long
double atof(const char* str); // 字符串转 double

long strtol(const char* str, char** endptr, int base); // 安全版本
double strtod(const char* str, char** endptr); // 安全版本

随机数

int rand(void);                      // 生成随机数(0 到 RAND_MAX)
void srand(unsigned int seed); // 设置随机种子

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
srand(time(NULL)); // 使用时间作为种子
for (int i = 0; i < 5; i++) {
printf("%d ", rand() % 100); // 0-99 的随机数
}
return 0;
}

程序控制

void exit(int status);               // 正常终止程序
void abort(void); // 异常终止程序
int atexit(void (*func)(void)); // 注册退出函数
int system(const char* command); // 执行系统命令
void cleanup(void) {
printf("程序即将退出\n");
}

int main(void) {
atexit(cleanup); // 注册清理函数
printf("程序运行中...\n");
return 0; // 退出时自动调用 cleanup
}

排序与搜索

void qsort(void* base, size_t n, size_t size, 
int (*compar)(const void*, const void*));
void* bsearch(const void* key, const void* base, size_t n, size_t size,
int (*compar)(const void*, const void*));
int compare_int(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}

int main(void) {
int arr[] = {5, 2, 8, 1, 9, 3, 7, 4, 6};
int n = sizeof(arr) / sizeof(arr[0]);

qsort(arr, n, sizeof(int), compare_int);

for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");

int key = 5;
int* result = bsearch(&key, arr, n, sizeof(int), compare_int);
if (result != NULL) {
printf("找到: %d\n", *result);
}

return 0;
}

整数运算

int abs(int n);                      // 绝对值
long labs(long n);
div_t div(int numer, int denom); // 除法,返回商和余数
div_t result = div(17, 5);
printf("商: %d, 余数: %d\n", result.quot, result.rem); // 商: 3, 余数: 2

字符串库 string.h

字符串操作

size_t strlen(const char* str);      // 字符串长度
char* strcpy(char* dest, const char* src); // 复制字符串
char* strncpy(char* dest, const char* src, size_t n); // 安全复制
char* strcat(char* dest, const char* src); // 连接字符串
char* strncpy(char* dest, const char* src, size_t n); // 安全连接

字符串比较

int strcmp(const char* s1, const char* s2);   // 比较字符串
int strncmp(const char* s1, const char* s2, size_t n); // 比较前 n 个字符

返回值:小于 0(s1 < s2)、等于 0(相等)、大于 0(s1 > s2)。

字符串搜索

char* strchr(const char* str, int ch);   // 查找字符(首次出现)
char* strrchr(const char* str, int ch); // 查找字符(最后出现)
char* strstr(const char* haystack, const char* needle); // 查找子串
char* strtok(char* str, const char* delim); // 分割字符串
char str[] = "Hello, World!";
char* p = strchr(str, 'o'); // "o, World!"
char* q = strstr(str, "World"); // "World!"

char text[] = "apple,banana,orange";
char* token = strtok(text, ",");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ",");
}

内存操作

void* memcpy(void* dest, const void* src, size_t n);  // 内存复制
void* memmove(void* dest, const void* src, size_t n); // 内存移动(允许重叠)
void* memset(void* str, int c, size_t n); // 设置内存
int memcmp(const void* s1, const void* s2, size_t n); // 内存比较
void* memchr(const void* str, int c, size_t n); // 内存搜索
int arr[10];
memset(arr, 0, sizeof(arr)); // 全部设置为 0

int src[] = {1, 2, 3, 4, 5};
int dst[5];
memcpy(dst, src, sizeof(src)); // 复制数组

字符处理库 ctype.h

字符分类

int isalpha(int c);   // 是否字母
int isdigit(int c); // 是否数字
int isalnum(int c); // 是否字母或数字
int isspace(int c); // 是否空白字符
int isupper(int c); // 是否大写字母
int islower(int c); // 是否小写字母
int ispunct(int c); // 是否标点符号
int isprint(int c); // 是否可打印字符
int iscntrl(int c); // 是否控制字符
int isxdigit(int c); // 是否十六进制数字

字符转换

int toupper(int c);   // 转大写
int tolower(int c); // 转小写
char str[] = "Hello, World!";

for (int i = 0; str[i] != '\0'; i++) {
str[i] = tolower(str[i]);
}
printf("%s\n", str); // hello, world!

// 统计字母数量
int letters = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i])) {
letters++;
}
}

数学库 math.h

基本运算

double fabs(double x);      // 绝对值
double fmod(double x, double y); // 取模
double pow(double x, double y); // 幂运算
double sqrt(double x); // 平方根
double cbrt(double x); // 立方根(C99)

取整函数

double ceil(double x);      // 向上取整
double floor(double x); // 向下取整
double round(double x); // 四舍五入(C99)
double trunc(double x); // 截断小数(C99)

指数与对数

double exp(double x);       // e^x
double log(double x); // 自然对数
double log10(double x); // 以 10 为底的对数
double log2(double x); // 以 2 为底的对数(C99)

三角函数

double sin(double x);       // 正弦
double cos(double x); // 余弦
double tan(double x); // 正切
double asin(double x); // 反正弦
double acos(double x); // 反余弦
double atan(double x); // 反正切
double atan2(double y, double x); // 双参数反正切

其他函数

double hypot(double x, double y);  // 斜边长度 sqrt(x² + y²)
double ldexp(double x, int exp); // x * 2^exp
double frexp(double x, int* exp); // 分解为尾数和指数
#include <math.h>
#include <stdio.h>

int main(void) {
printf("sqrt(16) = %f\n", sqrt(16)); // 4.0
printf("pow(2, 10) = %f\n", pow(2, 10)); // 1024.0
printf("ceil(3.2) = %f\n", ceil(3.2)); // 4.0
printf("floor(3.8) = %f\n", floor(3.8)); // 3.0
printf("round(3.5) = %f\n", round(3.5)); // 4.0
printf("fabs(-5.5) = %f\n", fabs(-5.5)); // 5.5

double angle = M_PI / 4; // 45 度
printf("sin(45°) = %f\n", sin(angle)); // 0.707...
printf("cos(45°) = %f\n", cos(angle)); // 0.707...

return 0;
}

时间库 time.h

时间类型

time_t         // 日历时间类型
struct tm // 分解的时间结构
clock_t // 处理器时间类型

struct tm 成员:

成员说明范围
tm_sec0-60
tm_min0-59
tm_hour0-23
tm_mday1-31
tm_mon0-11
tm_year年(从 1900 起)
tm_wday星期0-6
tm_yday年内天数0-365
tm_isdst夏令时标志

时间函数

time_t time(time_t* timer);              // 获取当前时间
struct tm* localtime(const time_t* timer); // 转换为本地时间
struct tm* gmtime(const time_t* timer); // 转换为 UTC 时间
char* ctime(const time_t* timer); // 时间转字符串
char* asctime(const struct tm* tm); // tm 转字符串
time_t mktime(struct tm* tm); // tm 转 time_t
size_t strftime(char* str, size_t max, const char* format, const struct tm* tm); // 格式化时间
#include <time.h>
#include <stdio.h>

int main(void) {
time_t now = time(NULL);
printf("当前时间戳: %ld\n", now);

char* time_str = ctime(&now);
printf("ctime: %s", time_str);

struct tm* local = localtime(&now);
printf("年: %d\n", local->tm_year + 1900);
printf("月: %d\n", local->tm_mon + 1);
printf("日: %d\n", local->tm_mday);

char buffer[100];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local);
printf("格式化: %s\n", buffer);

return 0;
}

计时

clock_t clock(void);  // 获取处理器时间
double difftime(time_t end, time_t start); // 计算时间差
#include <time.h>
#include <stdio.h>

int main(void) {
clock_t start = clock();

// 执行一些操作
volatile long sum = 0;
for (long i = 0; i < 100000000; i++) {
sum += i;
}

clock_t end = clock();
double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("耗时: %.3f 秒\n", elapsed);

return 0;
}

断言库 assert.h

void assert(int expression);  // 运行时断言
#include <assert.h>

void process(int* ptr, int size) {
assert(ptr != NULL);
assert(size > 0);

for (int i = 0; i < size; i++) {
ptr[i] = i * 2;
}
}

定义 NDEBUG 可以禁用断言:

#define NDEBUG
#include <assert.h> // 断言被禁用

布尔类型 stdbool.h(C99)

#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
#include <stdbool.h>

bool is_even(int n) {
return n % 2 == 0;
}

int main(void) {
bool flag = true;
if (flag) {
printf("flag is true\n");
}
return 0;
}

固定宽度整数 stdint.h(C99)

int8_t      // 8 位有符号整数
int16_t // 16 位有符号整数
int32_t // 32 位有符号整数
int64_t // 64 位有符号整数

uint8_t // 8 位无符号整数
uint16_t // 16 位无符号整数
uint32_t // 32 位无符号整数
uint64_t // 64 位无符号整数

intptr_t // 能容纳指针的整数
uintptr_t // 能容纳指针的无符号整数
#include <stdint.h>
#include <stdio.h>

int main(void) {
int32_t value = 2147483647;
uint64_t big_value = 18446744073709551615ULL;

printf("int32_t 大小: %zu\n", sizeof(int32_t)); // 4
printf("int64_t 大小: %zu\n", sizeof(int64_t)); // 8

return 0;
}

小结

本章介绍了 C 语言常用标准库:

  • <stdio.h>:输入输出
  • <stdlib.h>:内存管理、随机数、排序搜索
  • <string.h>:字符串和内存操作
  • <ctype.h>:字符分类和转换
  • <math.h>:数学函数
  • <time.h>:时间日期
  • <assert.h>:断言
  • <stdbool.h>:布尔类型
  • <stdint.h>:固定宽度整数

下一章将学习 知识速查表,提供快速参考。