标准库常用函数

C语言标准库(Standard Library)提供了一系列预定义的函数、类型和宏,极大地扩展了C语言的能力。 标准库涵盖了输入输出、字符串处理、数学计算、内存管理、时间日期等各个方面。 熟练掌握这些常用函数,可以显著提高编程效率,避免重复造轮子。本章将分类介绍最常用的标准库函数及其使用方法。

📁 stdio.h - 输入输出函数

<stdio.h> 是最常用的头文件,提供了文件操作和标准输入输出函数。

🔸 标准输入输出

函数功能示例
printf格式化输出到stdoutprintf("x=%d\n", x);
scanf从stdin格式化输入scanf("%d", &x);
putchar输出单个字符putchar('A');
getchar读取单个字符int ch = getchar();
puts输出字符串并换行puts("Hello");
gets⚠️ 不安全,已废弃使用 fgets 替代

🔸 文件操作

函数功能示例
fopen打开文件FILE *fp = fopen("a.txt", "r");
fclose关闭文件fclose(fp);
fprintf格式化写入文件fprintf(fp, "%d", x);
fscanf从文件格式化读取fscanf(fp, "%d", &x);
fputc写入字符fputc('A', fp);
fgetc读取字符int ch = fgetc(fp);
fputs写入字符串fputs("Hello", fp);
fgets安全读取一行fgets(buf, sizeof(buf), fp);
fread二进制读fread(data, sizeof(int), 10, fp);
fwrite二进制写fwrite(data, sizeof(int), 10, fp);
fseek移动文件位置fseek(fp, 0, SEEK_SET);
ftell获取当前文件位置long pos = ftell(fp);
rewind回到文件开头rewind(fp);

🔧 stdlib.h - 通用工具函数

<stdlib.h> 提供了内存管理、随机数、字符串转换、程序退出等函数。

🔸 内存管理

void *malloc(size_t size);      // 分配内存
void *calloc(size_t nmemb, size_t size); // 分配并清零
void *realloc(void *ptr, size_t size);   // 重新分配
void free(void *ptr);           // 释放内存

🔸 随机数

int rand(void);                 // 返回0到RAND_MAX之间的伪随机数
void srand(unsigned int seed);  // 设置随机数种子
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    srand(time(NULL));           // 用当前时间作为种子
    int r = rand() % 100;        // 生成0-99的随机数
    printf("随机数: %d\n", r);
    return 0;
}

🔸 字符串转换

函数功能示例
atoi字符串转intint n = atoi("123");
atol字符串转longlong l = atol("123456");
atof字符串转doubledouble d = atof("3.14");
strtol字符串转long(可检测错误)char *end; long val = strtol("123abc", &end, 10);
strtod字符串转doubledouble d = strtod("3.14", NULL);

🔸 程序控制

void exit(int status);      // 终止程序,返回状态码
void abort(void);           // 异常终止
int system(const char *cmd); // 执行系统命令
system("cls");  // Windows清屏
system("clear"); // Linux清屏

🔸 快速排序

void qsort(void *base, size_t nmemb, size_t size,
           int (*compar)(const void *, const void *));

📝 string.h - 字符串处理函数

函数功能示例
strlen求字符串长度size_t len = strlen("abc");
strcpy复制字符串(不安全)strcpy(dest, src);
strncpy限制长度复制strncpy(dest, src, n); dest[n-1]='\0';
strcat拼接字符串(不安全)strcat(dest, src);
strncat限制长度拼接strncat(dest, src, n);
strcmp比较字符串if (strcmp(s1, s2) == 0) ...
strncmp限制长度比较strncmp(s1, s2, 3);
strchr查找字符首次出现char *p = strchr(str, 'c');
strrchr查找字符最后一次出现char *p = strrchr(str, 'c');
strstr查找子串char *p = strstr(str, "abc");
strtok字符串分割char *token = strtok(str, ",");
memset设置内存块值memset(arr, 0, sizeof(arr));
memcpy内存复制memcpy(dest, src, n);
memmove内存复制(处理重叠)memmove(dest, src, n);
memcmp比较内存块if (memcmp(a, b, n) == 0) ...

📐 math.h - 数学函数

使用 math.h 中的函数时,编译时需要链接数学库:gcc prog.c -lm(Linux/macOS)。

函数功能示例
sin, cos, tan三角函数(弧度)double s = sin(3.14159/2);
asin, acos, atan反三角函数double a = asin(1.0);
exp, log, log10指数、自然对数、常用对数double e = exp(1.0);
pow幂函数double p = pow(2.0, 3.0); // 8.0
sqrt平方根double s = sqrt(16.0); // 4.0
fabs浮点数绝对值double a = fabs(-3.14);
ceil, floor向上取整、向下取整ceil(3.2) → 4.0, floor(3.2) → 3.0
fmod浮点数取余double r = fmod(5.5, 2.0); // 1.5

🔤 ctype.h - 字符测试函数

这些函数用于判断字符类型和转换大小写。

函数功能示例
isalnum字母或数字if (isalnum(ch)) ...
isalpha字母if (isalpha(ch)) ...
isdigit数字if (isdigit(ch)) ...
islower小写字母if (islower(ch)) ...
isupper大写字母if (isupper(ch)) ...
isspace空白字符(空格、换行、制表等)if (isspace(ch)) ...
ispunct标点符号if (ispunct(ch)) ...
tolower转换为小写char c = tolower('A');
toupper转换为大写char c = toupper('a');
#include <ctype.h>
#include <stdio.h>

int main() {
    char str[] = "Hello, World! 123";
    for (int i = 0; str[i]; i++) {
        if (isalpha(str[i]))
            putchar(toupper(str[i]));
        else
            putchar(str[i]);
    }
    // 输出:HELLO, WORLD! 123
    return 0;
}

⏰ time.h - 时间日期函数

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

int main() {
    // 获取当前时间戳(秒)
    time_t t = time(NULL);
    printf("当前时间戳: %ld\n", t);

    // 转换为本地时间字符串
    struct tm *tm = localtime(&t);
    printf("本地时间: %s", asctime(tm));

    // 格式化输出时间
    char buf[64];
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
    printf("格式化时间: %s\n", buf);

    // 计算程序运行时间
    clock_t start = clock();
    // 模拟耗时操作
    for (volatile int i = 0; i < 100000000; i++);
    clock_t end = clock();
    printf("耗时: %.2f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);

    return 0;
}
注意: clock() 测量的是CPU时间,而非真实流逝时间。如果需要高精度计时,可使用平台相关函数。

📋 综合示例:实现简易文件复制工具

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

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "用法: %s 源文件 目标文件\n", argv[0]);
        return 1;
    }

    FILE *src = fopen(argv[1], "rb");
    if (src == NULL) {
        perror("打开源文件失败");
        return 1;
    }

    FILE *dst = fopen(argv[2], "wb");
    if (dst == NULL) {
        perror("创建目标文件失败");
        fclose(src);
        return 1;
    }

    char buffer[4096];
    size_t bytes;
    while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) {
        fwrite(buffer, 1, bytes, dst);
    }

    fclose(src);
    fclose(dst);
    printf("复制完成\n");
    return 0;
}

⚠️ 常见错误与注意事项

  • 忘记包含头文件:使用标准库函数前必须包含对应的头文件,否则编译器会隐式声明(C89)或报错(C99+)。
  • 字符串函数缓冲区溢出:使用 strcpystrcat 等不安全函数时,务必确保目标缓冲区足够大。优先使用 strncpystrncatsnprintf
  • math.h 函数未链接数学库:在Linux/macOS下编译时需加 -lm 选项。
  • rand() 未设置种子:每次运行生成的随机数序列相同,应调用 srand(time(NULL)) 设置种子。
  • 文件操作未检查返回值fopenfreadfwrite 等应检查返回值,避免使用无效文件指针。
  • 混淆 sizeof 与 strlensizeof 返回数组占用的字节数,strlen 返回字符串长度(不含'\0')。
  • 使用 getsgets 已被C11废弃,因为它无法防止缓冲区溢出,应使用 fgets

标准库是C语言的宝藏,熟练掌握常用函数可以事半功倍。建议多查阅C标准库文档(如cppreference.com),并亲手编写示例程序加深理解。 至此,C语言核心内容已基本覆盖,后续可结合项目实践进一步提升。