在 C 语言开发中,字符和字符串的处理是高频操作。C 语言标准库提供了一系列字符函数和字符串函数来简化开发流程。本文将对这些函数进行全面解析,包含功能说明、使用示例、模拟实现以及避坑要点,帮助大家彻底掌握这些工具函数。

目录

一、字符分类函数

1. 常用函数列表

2. 使用示例:小写字母转大写

二、字符转换函数

1. 函数说明

2. 优势

三、核心字符串函数(用法 + 模拟实现)

1. 长度计算:strlen

2. 字符串拷贝:strcpy

3. 字符串追加:strcat

4. 字符串比较:strcmp

四、更安全的字符串函数(带 n 限制)

1. strncpy

2. strncat

3. strncmp

五、其他实用字符串函数

1. 字符串查找:strstr

2. 字符串分割:strtok

3. 错误信息获取:strerror

六、避坑指南

七、总结


一、字符分类函数

字符分类函数用于判断一个字符的类型,比如是否为数字、字母、小写字母等。这类函数的使用需要包含头文件 ctype.h

1. 常用函数列表

2. 使用示例:小写字母转大写

#include <stdio.h>
#include <ctype.h>

int main()
{
    int i = 0;
    char str[] = "Test String.\n";
    char c;
    while (str[i])
    {
        c = str[i];
        // 判断是否为小写字母
        if (islower(c))
            // 转大写
            c = toupper(c);
        putchar(c);
        i++;
    }
    return 0;
}

二、字符转换函数

字符转换函数同样依赖 ctype.h 头文件,主要包含两个函数,用于大小写字母的互相转换。

1. 函数说明

  • tolower(int c):将大写字母转换为小写,非大写字母不处理
  • toupper(int c):将小写字母转换为大写,非小写字母不处理

2. 优势

相较于手动通过加减 32 实现转换,使用函数更具可读性和可移植性。

三、核心字符串函数(用法 + 模拟实现)

这部分是字符串处理的核心,包含长度计算、拷贝、追加、比较等函数。使用这些函数需要包含头文件 string.h

1. 长度计算:strlen

  • 函数原型size_t strlen(const char *str)

  • 功能:计算字符串长度,统计 \0 之前的字符个数

  • 注意事项

    1. 字符串必须以 \0 结尾,否则会出现越界访问
    2. 返回值 size_t 是无符号整数,相减时容易出错
  • 模拟实现(三种方式)

#include <assert.h>

// 方式1:计数器法
int my_strlen(const char* str)
{
    assert(str);
    int count = 0;
    while (*str)
    {
        count++;
        str++;
    }
    return count;
}

// 方式2:递归法(无临时变量)
int my_strlen(const char* str)
{
    assert(str);
    if (*str == '\0')
        return 0;
    return 1 + my_strlen(str + 1);
}

// 方式3:指针-指针法
int my_strlen(char* s)
{
    assert(s);
    char* p = s;
    while (*p != '\0')
        p++;
    return p - s;
}

2. 字符串拷贝:strcpy

  • 函数原型char* strcpy(char *dest, const char *src)

  • 功能:将源字符串拷贝到目标空间,包含 \0

  • 注意事项

    1. 源字符串必须以 \0 结尾
    2. 目标空间需足够大且可修改
  • 模拟实现

#include <assert.h>

char* my_strcpy(char* dest, const char* src)
{
    assert(dest && src);
    char* ret = dest;
    while ((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

3. 字符串追加:strcat

  • 函数原型char* strcat(char *dest, const char *src)

  • 功能:将源字符串追加到目标字符串末尾

  • 注意事项

    1. 源字符串和目标字符串都要以 \0 结尾
    2. 目标空间需足够容纳拼接后的字符串
  • 模拟实现

#include <assert.h>

char* my_strcat(char* dest, const char* src)
{
    assert(dest && src);
    char* ret = dest;
    // 找到目标字符串的末尾
    while (*dest)
    {
        dest++;
    }
    // 追加源字符串
    while ((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

4. 字符串比较:strcmp

  • 函数原型int strcmp(const char *str1, const char *str2)

  • 功能:按 ASCII 码值比较两个字符串

  • 返回值规则

    1. str1 > str2,返回大于 0 的数
    2. str1 == str2,返回 0
    3. str1 < str2,返回小于 0 的数
  • 模拟实现

#include <assert.h>

int my_strcmp(const char* str1, const char* str2)
{
    assert(str1 && str2);
    while (*str1 == *str2)
    {
        if (*str1 == '\0')
            return 0;
        str1++;
        str2++;
    }
    return *str1 - *str2;
}

四、更安全的字符串函数(带 n 限制)

上述 strcpystrcatstrcmp 存在越界风险,对应的带 n 版本函数可以指定操作长度,更安全。

1. strncpy

  • 函数原型char* strncpy(char *dest, const char *src, size_t num)
  • 功能:最多拷贝 num 个字符到目标空间
  • 特点:若源字符串长度小于 num,剩余部分用 \0 填充

2. strncat

  • 函数原型char* strncat(char *dest, const char *src, size_t num)
  • 功能:最多追加 num 个字符到目标字符串末尾
  • 特点:追加完成后自动添加 \0

3. strncmp

  • 函数原型int strncmp(const char *str1, const char *str2, size_t num)
  • 功能:最多比较前 num 个字符

五、其他实用字符串函数

1. 字符串查找:strstr

  • 函数原型char* strstr(const char *str1, const char *str2)
  • 功能:在 str1 中查找 str2 第一次出现的位置
  • 返回值:找到返回对应指针,未找到返回 NULL

2. 字符串分割:strtok

  • 函数原型char* strtok(char *str, const char *sep)

  • 功能:按照分隔符集合 sep 分割字符串 str

  • 使用特点

    1. 第一次调用传入 str,后续调用传入 NULL
    2. 函数会修改原字符串,建议使用临时拷贝
  • 使用示例

#include <stdio.h>
#include <string.h>

int main()
{
    char arr[] = "192.168.6.111";
    char* sep = ".";
    char* str = NULL;
    for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
    {
        printf("%s\n", str);
    }
    return 0;
}

3. 错误信息获取:strerror

  • 函数原型char* strerror(int errnum)

  • 功能:将错误码转换为对应的错误信息字符串

  • 使用:需包含 errno.h,配合全局变量 errno 使用

  • 示例

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
    FILE* pFile = fopen("unexist.ent", "r");
    if (pFile == NULL)
        printf("Error: %s\n", strerror(errno));
    return 0;
}

六、避坑指南

  1. strlen 返回值陷阱size_t 是无符号数,strlen(str2)-strlen(str1) 永远不会为负
  2. strcpy 目标空间问题:必须确保目标空间可修改且足够大,避免数组越界
  3. strcat 自追加问题:不能用 strcat(str, str),会覆盖 \0 导致死循环
  4. strtok 修改原字符串:如需保留原字符串,先进行拷贝

七、总结

字符函数和字符串函数是 C 语言处理文本数据的基础,掌握这些函数的用法、注意事项和底层实现,不仅能提升代码质量,还能避免常见的内存越界、逻辑错误。建议大家手动实现这些函数,加深对字符串处理逻辑的理解。

如果本篇内容对你有帮助,欢迎点赞、收藏、关注!有任何疑问,评论区留言交流~

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐