C 语言字符串入门:字符函数 + strlen 精讲(从使用到模拟实现)

🏠个人主页:黎雁

🎬作者简介:C/C++/JAVA后端开发学习者

❄️个人专栏:C语言数据结构(C语言)EasyX游戏规划

✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

    • [一、字符处理函数:分类+转换 📚](#一、字符处理函数:分类+转换 📚)
      • [1. 字符分类函数:精准判断字符属性](#1. 字符分类函数:精准判断字符属性)
      • [2. 字符转换函数:快速切换大小写](#2. 字符转换函数:快速切换大小写)
    • [二、strlen:字符串长度计算的坑与实现 🚨](#二、strlen:字符串长度计算的坑与实现 🚨)
    • [写在最后 📝](#写在最后 📝)

在C语言的字符串操作领域,字符处理函数和 strlen 是绕不开的基础内容。它们不仅是日常代码编写的常用工具,更是笔面试中考察字符串基础能力的高频考点。今天这篇文章,就带大家吃透字符分类、转换函数,以及 strlen 的使用陷阱和三种模拟实现方式!

一、字符处理函数:分类+转换 📚

字符分类与转换函数是处理单个字符的核心工具,使用时需要包含头文件 <ctype.h>。掌握这些函数,能让我们对字符的筛选、转换操作变得简洁高效。

1. 字符分类函数:精准判断字符属性

这类函数的参数是字符的ASCII码值(传入char类型会自动提升为int),返回值为非零(真)0(假)。常用函数及功能如下表所示:

函数 功能说明 典型应用场景
iscntrl 判断是否为控制字符(ASCII 0~31、127) 过滤不可打印的控制字符
isspace 判断是否为空白字符(空格、\n、\t、\r等) 去除字符串首尾空格
isdigit 判断是否为十进制数字 0-9 提取字符串中的数字字符
islower 判断是否为小写字母 a-z 字符串统一转大写
isupper 判断是否为大写字母 A-Z 字符串统一转小写
isalpha 判断是否为字母(a-z / A-Z 校验输入是否为纯字母
isalnum 判断是否为字母或数字 校验账号密码合法性
ispunct 判断是否为标点符号(非字母、数字、空格) 文本符号的筛选统计

💡 实战示例:提取字符串中的数字字符

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main()
{
    char arr[] = "abcdef1w2#gty78";
    int i = 0;
    while (arr[i] != '\0')
    {
        if (isdigit(arr[i])) // 判断当前字符是否为数字
        {
            printf("%c ", arr[i]);
        }
        i++;
    }
    // 运行输出:1 2 7 8
    return 0;
}

2. 字符转换函数:快速切换大小写

C语言提供了两个专门用于字母大小写转换的函数,用法简单且高效:

  • tolower(int c):将大写字母转为小写,非字母字符返回原值
  • toupper(int c):将小写字母转为大写,非字母字符返回原值

优化示例:将字符串中的小写字母转为大写

对比手动计算ASCII码差值的方式,使用toupper函数的代码更简洁易读:

c 复制代码
#include <stdio.h>
#include <ctype.h>
int main()
{
    char arr[] = "aCbCdeF12w#gTy78";
    int i = 0;
    while (arr[i] != '\0')
    {
        if (islower(arr[i])) // 先判断是否为小写字母
        {
            arr[i] = toupper(arr[i]); // 转为大写
        }
        printf("%c", arr[i]);
        i++;
    }
    // 运行输出:ACBCDEF12W#GTY78
    return 0;
}

二、strlen:字符串长度计算的坑与实现 🚨

strlen 是用来计算字符串长度的库函数,使用时需要包含头文件 <string.h>。这个函数看似简单,但暗藏不少易错点,同时它的模拟实现也是笔面试的常客。

1. 函数核心要点:必须掌握的3个细节

  • 函数原型size_t strlen(const char* str);
    这里的返回值 size_t 是一个无符号整数类型 (本质是 unsigned int),这是最容易踩坑的地方!
  • 计算规则 :从传入地址开始,向后统计字符个数,直到遇到 \0 停止,不包含 \0 本身
  • 打印格式 :推荐使用 %zd 来匹配 size_t 类型,避免格式不匹配导致的输出错误。

经典踩坑:无符号数的比较陷阱

由于 strlen 返回无符号数,直接用它的返回值做减法比较,会出现和直觉相反的结果:

c 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[] = "abcdef"; // 长度6
    char arr2[] = "abc";    // 长度3
    // 坑点:3-6 = -3,无符号数中-3会被视为极大值
    if (strlen(arr2) - strlen(arr1) >= 0)
    {
        printf("arr2>arr1\n"); // 错误输出!
    }
    else
    {
        printf("arr2<=arr1\n");
    }

    // 正确解法1:改为直接比较
    if (strlen(arr2) >= strlen(arr1)) {}
    // 正确解法2:强制转为有符号整数
    if ((int)strlen(arr2) - (int)strlen(arr1) >= 0) {}
    return 0;
}

2. strlen三种模拟实现:笔面试高频考点

模拟实现 strlen 有三种经典思路,分别对应不同的编程思想,我们逐一讲解并实现。

实现前要注意:传入的字符串指针可能为NULL ,所以需要用 assert 断言来保证代码健壮性,使用时需包含 <assert.h>

方式1:计数器法(最易理解)

核心思路 :定义一个计数器变量,遍历字符串,每访问一个非 \0 字符,计数器加1,直到遇到 \0 停止。

c 复制代码
size_t my_strlen1(const char* str)
{
    assert(str != NULL); // 防止传入空指针
    size_t count = 0;
    while (*str++) // 先判断*str是否为\0,再让指针后移
    {
        count++;
    }
    return count;
}
方式2:指针-指针法(空间最优)

核心思路 :利用指针运算的特性------两个指向同一数组的指针相减,结果为指针之间的元素个数

c 复制代码
size_t my_strlen2(const char* str)
{
    assert(str); // 简写:str为NULL时断言失败
    const char* p = str; // 保存起始地址
    while (*p) // 找到\0的位置
    {
        p++;
    }
    return p - str; // 指针差值即字符串长度
}
方式3:递归法(无临时变量)

核心思路 :递归的本质是把大问题拆成小问题。计算 str 的长度 = 1 + 计算 str+1 的长度,直到 str 指向 \0 时返回0。

c 复制代码
size_t my_strlen3(const char* str)
{
    assert(str);
    if (*str == '\0')
        return 0;
    else
        return 1 + my_strlen3(str + 1); // 递归调用
}

💡 测试三种实现方式

c 复制代码
#include <stdio.h>
#include <assert.h>
// 上面的三个my_strlen函数写在这里
int main()
{
    char arr[] = "abcdef";
    printf("%zd\n", my_strlen1(arr)); // 输出:6
    printf("%zd\n", my_strlen2(arr)); // 输出:6
    printf("%zd\n", my_strlen3(arr)); // 输出:6
    return 0;
}

写在最后 📝

字符分类和转换函数是字符串处理的"基本功",熟练使用它们能大幅提升代码效率;而 strlen 函数的核心陷阱在于无符号返回值,笔试时一定要警惕这个易错点。

三种模拟实现 strlen 的方法,分别体现了"迭代""指针运算"和"递归"三种编程思路,笔面试中很可能会要求手写其中一种,建议大家都动手敲一遍加深理解。

下一篇文章,我们将聚焦字符串操作的核心函数------strcpystrcat,讲解它们的使用规则、注意事项以及模拟实现,帮你吃透长度不受限制的字符串函数!

相关推荐
星环处相逢2 小时前
Docker资源限制全解析:CPU、内存、磁盘IO管控与实操指南
java·开发语言
white-persist2 小时前
【攻防世界】reverse | tt3441810 详细题解 WP
java·c语言·开发语言·数据结构·c++·算法·安全
四维碎片2 小时前
【Qt】为什么QList是数组
开发语言·qt
古城小栈2 小时前
Go + 区块链:模块化链节点开发实践
开发语言·golang·区块链
码luffyliu2 小时前
Go sync 标准库实战指南:吃透并发同步的核心工具
开发语言·后端·golang
量子炒饭大师2 小时前
Cyber骇客的树状逻辑数据——【初阶数据结构与算法】树
c语言·数据结构·c++·二叉树·
草莓熊Lotso2 小时前
C++ 异常完全指南:从语法到实战,优雅处理程序错误
android·java·开发语言·c++·人工智能·经验分享·后端
init_23612 小时前
MPLS跨域optionA 配置案例
java·开发语言·网络
墨有6662 小时前
【C++ 入门】类和对象(中)
开发语言·c++