目录
1.1————strlen的介绍及其模拟实现。
1.2————strcpy的介绍及其模拟实现。
1.3————strcat的介绍及其模拟实现。
1.4————strstr的介绍及其模拟实现。
1.5————strcmp的介绍及其模拟实现。
1.6————memcpy的介绍及其模拟实现。
1.7————memmove的介绍及其模拟实现。
1.1。strlen的介绍(计算字符串的长度)
①:字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
②:参数指向的字符串必须要以 '\0' 结束。
③:注意函数的返回值为size_t,是无符号的。
strlen的模拟实现
想要模拟实现strlen我们可以利用计数器的方式来计算,我们可以再我们模拟的函数中创建一个变量count用while循环来计算'\0'以前字符的个数,如图。
原理:我们将创建的变量count放在while循环中。while循环的判断条件为*str++。*str++中的++为后置++,所以会对str先进行解引用然后再执行str++,当*str不为'\0'时就会进入执行count++,知道遇到'\0'跳出循环然后返回count.从而达到计算的效果。
补充:图中的const的意义时防止字符串中的内容被改变增加函数的安全性。
assert的意义时防止传过来的地址为空指针也是增加函数的安全性。(使用assert时需要引入头文件<assert.h>)
1.2。strcpy的介绍
(将源指向的C字符串复制到目标指向的数组中,包括终止空字符(并在该点停止))
①:源字符串必须以 '\0' 结束。
②:会将源字符串中的 '\0' 拷贝到目标空间。
③:目标空间必须足够大,以确保能存放源字符串。
④:目标空间必须可变。
strcpy的模拟实现
想要模拟实现strcpy我们可以利用while循环来将源字符串中的拷贝到目标空间又因为strcpy函数需要将目标空间的起始地址返回所以我们需要在while循环前创建一个指针变量p来存放目标空间的起始地址。具体实现图下。
assert与count的作用还是保证函数的安全性。
1.3strcat的介绍
(将源字符串的副本附加到目标字符串。终止的空字符目标被源的第一个字符覆盖,空字符包含在由目标中的两个字符串联而成的新字符串的末尾。)
①:源字符串必须以 '\0' 结束。
②:目标空间必须有足够的大,能容纳下源字符串的内容。
③:目标空间必须可修改。
strcat的模拟实现
想要模拟实现strcat我们只需要在strcpy的基础上把目标空间点地址放在目标空间的'\0'处再重复我们上面实现的MyStrcpy即可实现。如下。
第一个while是将str1移动到目标空间的'\0'处,因为要指向'\0'所以不能在while循环的判断中++,第二个while循环就是将源空间的字符串copy到目标空间中从'\0'往后的空间中。
1.4strstr的介绍
(返回指向str1中第一个出现的str2的指针,如果str2不是str1的一部分,则返回空指针)
①:返回指向str1中第一个出现的str2的指针,如果str2不是str1的一部分,则返回空指针
strstr的模拟实现
如图我们首先可以在我们模拟的strstr函数内部再创建两个变量用来存放str1和str2的起始地址,
在第一个字符串中找第二个字符串需要先利用while循环将S1与S2进行比较.当s1与s2不同时就不可能再以a处开头找到与"bbc"相同的字符串,所以此时我能将cur1往后移动并且让s1与cur1对其,再次进行判断,当s1指向b时s2此时也指向b即(*s1 == *s2)时让s1与s2都往后移动一位。但此时当s2指向c时s1指向的确是b即(*s1 != *s2)就意味着当cur1指向第一个b时就不可能找出"bbc"。但此时s2已经指向了c,此时我们先前存放的cur2就发挥了作用,此时我们可以让s2与cur2再次对齐以进行再次筛选,知道cur1为指向第二个b时重复上述操作即可找到"bbc"。具体实现如图。
当*str2等于'\0'时即已经找到。此时返回的为cur中存放的地址。
而当*cur为'\0'时就表示找不到。此时返回的为NULL(空指针)。
如图。
1.5 strcmp的介绍
(此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或到达终止的空字符)
注意:strcmp比较的并非是两个字符串的长度,比较的是对应位置上字符的ASCII值。
①:第一个字符串大于第二个字符串,则返回大于0的数字。
②:第一个字符串等于第二个字符串,则返回0。
③:第一个字符串小于第二个字符串,则返回小于0的数字。
strcmp的模拟实现
先利用while循环来逐个判断*str1与*str2当*str1 == *str2就让str1与str2向后移动一位继续比较当一直移动到'\0'时都没有跳出while循环就返回两字符串相同返回0,当*str1 != *str2时直接返回(*str1 - *str2);
当*str1的ASCII值大于*str2的ASCII值时返回>0
当*str1的ASCII值小于*str2的ASCII值时返回<0
当*str1的ASCII值等于*str2的ASCII值时返回0
模拟实现的具体如下
1.6 memcpy的介绍
(作用与strcpy相似但其泛用性更广,不只能操作字符串。也可作用与其他类型)
①:这个函数在遇到 '\0' 的时候并不会停下来。
②:如果source和destination有任何的重叠,复制的结果都是未定义的。
③:函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
memcpy的模拟实现
因为memcpy的是对所以类型的的数组都可以进行操作,所以我们模拟实现memcpy时不能确定传过来的数组时哪种类型,因此我们需要用(void*)来进行接收。并且需要将其强制类型转换为(char*)的类型,以便于操作,这时我们传过来的(size_t)就发挥了作用,利用while循环来实现,如下。
memcpy的缺点
memcpy虽然可以对很多类型进行复制但是当出现以下情况原空间与目标空间发生重叠是就会出现一下情况
预期结果
实际结果
发生以上结果的原因是我们模拟实现的memcpy是从前往后进行覆盖的如图
介于以上情况就有了函数memmove来改善
1.7 memmove的介绍
(memmove的参数及其返回类型与memcpy的一样,具体不用体现在函数内部)
①:和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
②:如果源空间和目标空间出现重叠,就得使用memmove函数处理。
memmove的模拟实现
我们模拟实现的memcpy出现缺陷的原因是因为无论在什么情况下都是从前往后复制的,所以只要当我们分清楚情况(当源空间的起始地址小于目标空间时我们应该从后往前复制,反之应该从前往后复制)具体实现如下