字符串函数的模拟实现
创始人
2025-05-30 15:12:03

文章目录

  • 前言
  • 函数介绍
    • strlen 函数
    • strcpy 函数
    • strcat 函数
    • strcmp函数
    • strncpy
    • strncat
    • strncmp
    • strstr
    • strtok
    • strerror
    • memcpy 函数
    • memmove 函数
    • memcmp 函数

前言

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或者字符数组中。
字符串常量适用于那些对它不做修改的字符串函数。

函数介绍

strlen 函数

strlen函数是一个求字符串长度的函数,它遇到字符串末尾的’\0’结束计数,cplusplus网站上对这个函数的解释是这样的:
在这里插入图片描述

注意事项:
参数是一个char类型的指针,传入其他类型的变量会导致位置错误。
注意:

  • 函数的返回值为size_t(无符号整型)。
  • 参数指向的字符串必须以 ‘\0’ 结尾。

模拟实现strlen函数

#include 
// 计数器
size_t my_strlen1(const char* str )
{size_t count = 0;while (*str != '\0'){count++;str++;}return count;
}// 递归方法
size_t my_strlen2(const char* str)
{if (*str != '\0'){return 1 + my_strlen2(str + 1);}else{return 0;}
}
int main()
{char arr[10] = "abcdef";size_t ret1 = my_strlen1(arr);size_t ret2 = my_strlen2(arr);printf("函数一:%d\n",ret1);printf("函数二:%d\n",ret2);return 0;
}

运行结果:
在这里插入图片描述

strcpy 函数

strcpy的作用是将一个字符数组中的内容拷贝到另一个字符串数组中,返回值是目标空间的起始地址。
在这里插入图片描述
注意事项:
源字符串必须以 ‘\0’ 结束。
目标空间需要足够大,可以容纳源字符串的内容。
目标空间必须可修改。
模拟实现

char* my_strcpy(char* dest, const char* src)
{char* temp = dest;//会把/0拷贝过去,while (*dest++ = *src++){;}return temp;
}
int main()
{char arr[10] = { "abcdef" };char arr1[10] = { 0 };char* ret = my_strcpy(arr1, arr);printf("%s\n", ret);return 0;
}

strcat 函数

strcat 函数的作用是把一个字符串的内容追加到另一个字符串的后面,覆盖掉原来字符串里的 \0。从 \0 开始追加。
对于strcat函数的解释是这样的:
在这里插入图片描述
注意事项
源字符串末尾用**\0**结尾。
目标空间足够大,能容纳源字符串内容。
目标空间必须可修改。
字符串自己给自己追加,会发生指针越界访问。
在这里插入图片描述
模拟实现

strcat 的模拟实现char* my_strcat(char* destination, const char* source)
{char* temp = destination;//由于是从目标字符串的\0字符处开始追加的,那么我们可以//找到\0 去进行字符串的拷贝。while (*destination != '\0'){destination++;}while (*destination++ = *source++){;}//返回目标空间的起始地址。return temp;
}int main()
{char arr1[30] = "hello ";char arr2[10] = "world";char* ret = my_strcat(arr1, arr2);printf("%s\n", ret);return 0;
}

strcmp函数

它的作用是比较两个字符串的大小,小于返回小于零的数字,大于返回大于零的数字。
对于strcmp函数的解释是这样的:
在这里插入图片描述
模拟实现

int my_strcmp(const char* str1, const char* str2)
{//相等返回0//小于返回-1//大于返回1while (*str1 == *str2){//如果str1指向了末尾,说明是相等的if (*str1 == '\0'){return 0;}str1++;str2++;}if (*str1 - *str2 < 0){return -1;}else{return 1;}
}int main()
{char arr1[10] = "abc";char arr2[10] = "abcd";int ret = my_strcmp(arr1, arr2);printf("%d\n", ret);return 0;
}

以上的函数都是字符串长度不受控制的函数,这样就会出现一些安全问题。那么以下就是字符串长度受限制的函数。strcat函数是不适合自己给自己追加的而strncat是可以自己给自己追加的。
下面我们来练习一些长度受限制的字符串函数的使用:

strncpy

void test1()
{char arr[10] = "abcdef";char arr1[10] = { 0 };char* ret = strncpy(arr1, arr, 3);printf("%s\n", ret);
}

strncat

//strncat 的使用
void test2()
{char arr[20] = "abcdef";char* ret = strncat(arr, arr, 6);printf("%s\n", ret);
}

strncmp

//strncmp 的使用
void test3()
{char arr[10] = "abcdef";char arr1[10] = "abc";int ret = strncmp(arr, arr1, 3);printf("%d\n", ret);
}

strstr

strstr函数是在一个字符串里找子串。返回子串的开始位置。
它的内容是这样的:
在这里插入图片描述
模拟实现

//strstr 判断是否存在子字符串char* my_strstr(const char* str1, const char* str2)
{char* cp = str1;char* s1, *s2;while (*cp) //注意这里的cp是一个非常重要的地方{s1 = cp;s2 = str2;while (*s1 && *s2 && (*s1 == *s2)){s1++;s2++;}if (*s2=='\0'){return cp;}cp++;}return NULL;
}int main()
{char arr[10] = "abcdef";char arr1[10] = "bcd";char* ret = my_strstr(arr, arr1);printf("%s\n", ret);return 0;
}

strtok

strtok函数是按特殊符号分割字符串的。
内容是这样的:
在这里插入图片描述
注意事项

  • sep参数十个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
    strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
    并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
    中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
    记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。

strerror

strerror函数是返回错误码所对应的错误信息。C语言库函数在调用失败的时候,会把一个错误码放在一个叫errno的变量中,当我们想要知道调用库函数发生了什么错误的时候我们可以将错误码翻译成错误信息。
使用

//strerror 的使用
#include
int main()
{FILE* pf = fopen("text.txt", "r");printf("文件打开错误!%s\n", strerror(errno)); fclose(pf);pf = NULL;return 0;
}

memcpy 函数

是用来拷贝内存空间的。
解释:
在这里插入图片描述
注意事项

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 ** ‘\0’ ** 的时候并不会停下来。
  • 如果source合destination有任何重叠,复制的结果都是未定义的。

模拟实现

void* my_memcpy(void* dest, const void* src,size_t num)
{void* temp = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return temp;
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr1[10] = { 0 };my_memcpy(arr1, arr, 40);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}
}

memmove 函数

拷贝内存的函数
主要内容:
在这里插入图片描述
注意事项

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

模拟实现

void* my_memmove(void* dest, const void* src, size_t num)
{void* ret = dest;if (dest < src){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;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr + 2, arr, 12);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}
}

memcmp 函数

使用

/* memcmp example */
#include 
#include 
int main ()
{char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n;n=memcmp ( buffer1, buffer2, sizeof(buffer1) );if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);return 0;
}

相关内容

热门资讯

深入理解JVM虚拟机(二) 目录: (1)堆 (2)堆-内...
【Java SE】变量的本质 目录一. 前言二. 变量(variable)2.1 性质2.2 变量类型2.2.1 核心区别2.3 ...
金属的截止频率(红限)是什么,... 金属的截止频率(红限)是什么目录金属的截止频率(红限)是什么极限频率的介绍什么是金属的截止频率光电效...
曾国藩有那七句最著名的名言,曾... 曾国藩有那七句最著名的名言目录曾国藩有那七句最著名的名言曾国藩说过的名言名句。曾国藩的名言曾国藩名言...
二八佳人打一生肖(二八佳人打一... 今天给各位分享二八佳人打一生肖的知识,其中也会对二八佳人打一生肖是什么进行解释,如果能碰巧解决你现在...
水晶底是什么材质,nike 篮... 水晶底是什么材质目录水晶底是什么材质nike 篮球鞋水晶底氧化吗?水晶是什么材料玻璃杯水晶底和烧厚底...
从0开始学python -67 Python3 pip pip 是 Python 包管理工具,该工具提供了对 Pyth...
接入HMS Core应用内支付... 华为HMS Core应用内支付服务(In-App Purchases,I...
怎么用pscs6的路径选择工具... 怎么用pscs6的路径选择工具目录怎么用pscs6的路径选择工具ps如何选择路径ps如何选择路径区域...
电动车后面总是哒哒响asdad... 本篇文章极速百科给大家谈谈电动车后面总是哒哒响asdad1,以及电动车后面总是哒哒响维修视频对应的知...
新起亚K3的CVT耐用吗?起亚... 今天给各位分享新起亚K3的CVT耐用吗?起亚K3七速双离合到底好不好的知识,其中也会对起亚k314t...
职场kpl是什么意思,kpl在... 职场kpl是什么意思目录职场kpl是什么意思kpl在工作中是什么意思?职场kpl是什么意思职场kpl...
那些我在初级程序员阶段犯过的错 学习鉴别,形成习惯,避免犯错我要先说清楚一件事。如果你是一个初级程序员&...
完全小白的pycharm深度学... 完全小白的pycharm深度学习调试+for循环断点条件设置写在最前面基础方法pycharm...
MongoDB增加计算列并修改... 1. 增加、删除列 通过聚合,使用操作符$set增加列;修改结果...
阿里云PAI-DeepRec ... 阿里云联合英特尔举办的“创新大师杯”全球AI极客挑战赛——PAI-DeepRec CTR模型性能优化...
评价老师上课的评语有哪些,对上... 评价老师上课的评语有哪些目录评价老师上课的评语有哪些对上课教师课堂的评价怎样用专业术语评价任课老师讲...
噬血代码ign评分,噬血代码有... 噬血代码ign评分目录噬血代码ign评分噬血代码有缺陷是什么意思IGN评分是什么意思噬血代码能力值怎...
java并发 AQS 什么是AQS? 为什么它是核心?AQS的核心思想是什么? 它是怎么实现的? 底层数据结构等AQS有哪...
长喙的意思长喙解释(长喙的意思... 今天给各位分享长喙的意思长喙解释的知识,其中也会对长喙的意思和拼音进行解释,如果能碰巧解决你现在面临...
广西壮族自治区出租汽车司机崔腿... 今天给各位分享广西壮族自治区出租汽车司机崔腿粗师傅在四十四棵死涩...的知识,其中也会对广西壮族自治...
开发中常用多线程异步操作场景解... 场景一:批量操作,事务控制部分回滚 第一步:创建现场池,注意不同业务场景...
信息系统项目管理师 第2章 信... 1.信息技术及其发展 可分为硬技术(物化技术)传感器、服务器、智能手机、通信卫星和软技术(非物化技术...
【C++】一篇带你搞懂C++“... 前言在C语言的学习中,并没有引用这个概念,但是在C++中...
烧鸡怎么盘,烧鸡的腿怎么塞肚子... 烧鸡怎么盘目录烧鸡怎么盘烧鸡的腿怎么塞肚子里关记烧鸡的做法是什么?大盘烧鸡怎么做烧鸡怎么盘 烧...
on和upon的区别是什么,o... on和upon的区别是什么目录on和upon的区别是什么on和upon有什么区别?upon和on的区...
什么是圆呢圆的主要性质是什么,... 什么是圆呢圆的主要性质是什么目录什么是圆呢圆的主要性质是什么圆有哪些性质?圆的基本性质是什么圆的定义...
汽车雨刷刮不干净怎么办,雨刷刮... 汽车雨刷刮不干净怎么办目录汽车雨刷刮不干净怎么办雨刷刮不干净水怎么办汽车雨刮器刮不净怎么办?雨刮器刮...
[数据分析实战][37] 基于... 参考资料: 数据科学家赚多少?数据全分析与可视化-ShowMeAI 前言...
【面试专栏】SpringBoo... 1. 自定义线程池 1.1 示例代码 /*** 自定义线程池* * 优点:可以自定义参...