C语言常用字符串与内存库函数使用及模拟实现

小石头
小石头
发布时间:2026-10-13 | 5人浏览过
原创

C语言标准库提供了强大的字符串处理和内存操作接口,掌握这些库函数不仅有助于提升开发效率,更能通过模拟实现深入理解指针操作与内存模型。本文将逐一拆解 strlen、strcpy、strcmp、strcat、strstr、strtok 以及内存相关的 memcpy、memmove 等函数的原理与模拟代码,涵盖计数法、递归法及边界检查等关键实现细节。

字符串长度与拷贝:strlen 与 strcpy

第1步:理解并实现 strlen 计算字符串长度

strlen 返回字符串中 '\0' 之前的字符个数。模拟实现该函数有几种经典方法:

  • 计数法:通过指针遍历直到遇到终止符。
    int my_strlen(char* dest)
    {
        int count = 0;
        while (*dest) {
            count++;
            dest++;
        }
        return count;
    }
  • 指针减指针:记录起始位置,到达末尾后相减。
    int my_strlen(char* dest)
    {
        char* arr = dest;
        while (*arr++) ; // 移动到结尾的'\0'
        return (arr - dest) - 1; // 减去最后的空字符偏移
    }
  • 递归法:注意:递归版本在原文中存在逻辑错误(如参数传递不完整),在实际工程中应优先使用循环以实现栈安全。

第2步:掌握 strcpy 字符串拷贝

strcpy(destination, source) 将源串拷贝到目标空间,包含结束符 '\0'。使用前必须确保 destination 空间足够大且可写。

char* my_strcpy(char* dest, const char* str)
{
    char* ret = dest;
    while ((*dest++ = *str++) != '\0')
    {
        ; // 空循环体,利用赋值表达式的副作用
    }
    return ret;
}

关键点:拷贝过程依赖赋值表达式返回值,当 '\0' 被复制后循环停止,确保目标串以 '\0' 结尾。

字符串比较与连接:strcmp 与 strcat

第3步:字符串字典序比较 strcmp

strcmp(str1, str2) 从左向右逐字符比较 ASCII 值:
- 若相等则继续;
- 遇到不同字符时,返回 str1[i] - str2[i];
- 若均为 '\0' 则返回 0。

int my_strcmp(const char* s1, const char* s2)
{
    while (*s1 == *s2)
    {
        if (*s1 == '\0') return 0;
        s1++; s2++;
    }
    return *(unsigned char*)s1 - *(unsigned char*)s2;
}

第4步:字符串拼接 strcat

strcat(dest, src) 会将 src 追加到 dest 的末尾(覆盖 dest 原有的 '\0')。务必保证 dest 有足够的剩余空间,防止缓冲区溢出。

char* my_strcat(char* dest, const char* src)
{
    char* ret = dest;
    while (*dest) dest++;
    while ((*dest++ = *src++) != '\0');
    return ret;
}

子串查找与分割:strstr 与 strtok

第5步:模式匹配 strstr

strstr 用于在主串中查找子串首次出现的位置并返回指针。其本质是比较窗口滑动,需小心处理指针越界与回溯问题。

排错提醒:原文给出的 my_strstr 实现中嵌套了 while(*dest==*str) 逻辑,这会导致指针跳过部分匹配位或无法正确重置游标。标准的 strstr 需要两个游标:主串游标和子串匹配游标,发现不匹配时主串游标回退是低效做法,通常采用 KMP 或双重循环(每轮不匹配时主串+1)。

第6步:分隔符拆分 strtok

strtok 是非线程安全的动态状态函数。第一次调用传入待拆分字符串,后续调用传 NULL 以获取下一段。

char buff[] = "www.example@qq.com";
char buf[50]; 
strcpy(buf, buff);
char* sep = ".@";
char* token = strtok(buf, sep);
while(token != NULL){
    printf("%s\n", token);
    token = strtok(NULL, sep);
}

内存块操作:memcpy、memmove 与 memcmp

第7步:处理内存重叠 memcpy vs memmove

memcpy 不考虑内存重叠,行为未定义。若目的地址与源地址存在重叠,必须使用 memmove,它内部会自动判断方向(从前向后或从后向前拷贝)以保证数据安全。

void* my_memmove(void* dest, void* src, size_t num)
{
    assert(dest && src);
    void* ret = dest;
    if (dest < src || (char*)dest >= ((char*)src + num)) {
        // 前向拷贝(无重叠或源在目的之后)
        while (num--)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest + 1;
            src = (char*)src + 1;
        }
    } else {
        // 逆向拷贝(有重叠,防止源被覆盖)
        while (num--)
        {
            *((char*)dest + num) = *((char*)src + num);
        }
    }
    return ret;
}

第8步:二进制内存比较 memcmp

memcmp(ptr1, ptr2, num) 按字节逐个比较,遇到差异即返回差值,常用于结构体或整型数组的二进制对比,而非仅看数值大小。

字符属性分类判断

cctype 头文件中提供了诸多判断单字符性质的宏,使用时输入需为 unsigned char 或 EOF:

函数功能描述
isalpha字母 (A-Z, a-z)
isdigit数字 (0-9)
isspace空白符 (空格, \t, \n 等)
islower / isupper小写/大写英文字母
isxdigit十六进制字符
ispunct / isgraph / isprint标点 / 可见图形 / 全部可打印(含空格)

以上就是C语言常用字符串与内存库函数使用及模拟实现的详细内容,更多关于C语言底层内存管理与字符处理的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表