前言:
在学习编程代码中,我们不仅仅是要学会自己写出自定义函数,更要了解一些内部的库函数,因为这些函数都是进行了大量优化后而为我们更加方便使用所产生的。在c语言中,我将介绍关于字符串库函数以及内存库函数的一部分重要的库函数。
一 . 字符串函数
1.strlen函数的使用以及模拟实现
功能:
strlen函数是用于计算字符串'\0'之前(不包括'\0')的字符串长度的字符串库函数,值得注意的是计算的字符串末尾必须是'\0'结尾的才能算出有效值。
使用:
在c语言中,我们要使用strlen库函数,必须包含对应的头文件#include <string.h>。包含头文件后我们就可以正常的使用strlen函数,例如下面代码:

我们定义了一个数组,放进了字符串“abcdef”(注意末尾有'\0'),使用strlen函数即可计算出长度大小为6。
对于strlen相关的参数,可以参照下图:

对于strlen函数,它的返回值为无符号整形的size_t类型的数据,所以我们打印出结果时应该使用%zu来打印;
接着是strlen的形参,这里要给strlen函数传入的是一个指针,即是要计算字符串长度的字符串的首字符地址,对于数组,数组名表示首元素的地址,故我们可以写成strlen(str),这里还要注意的是我们传入的字符串地址,我们只是想计算其长度,而不去改变字符串的内容,故应该用const char* str 来限制它的内容。
另一种写法:
除了上面的写法,我们也可以直接将字符串写入实参部分,即如下图:

这里"abcdef"实际传进去的是首字符'a'的地址,和上述一样也可以计算出其长度。
模拟实现:
根据strlen库函数的返回值以及形参的形式,我们也可以自己模拟实现一个my_strlen的函数,接下来我会讲述三种实现strlen函数功能的模拟函数。
第一种:计数器方法

第二种:不创建临时变量的方法(函数递归)

第三种:指针-指针方法

补充(注意):
strlen计算的字符串必须是以'\0'为末尾的字符串,例如下面的代码:

这个数组是以'f'结尾的,即是没有'\0'的情况,如果我们也要用strlen计算它的长度,而strlen会一直找,直到找到内存中的'\0'才会停止返回一个数值,所以这里计算出来的结果是一个随机值,并且这个随机值一定比6大。
2.strcpy函数的使用以及模拟实现
功能:
strcpy是拷贝字符串的库函数,即有一个字符串目的地,也有一个字符串源头,简单的理解就是把源头的字符串拷贝到字符串目的地。
使用:
同样的,我们要想使用strcpy库函数,要包含对应的头文件,即#include <string.h>。使用strcpy,例如下图:

使用strcpy,相当于把src数组里面的”neymarjr“拷贝到dest数组上,并且是从dest数组的第一个字符的位置开始拷贝,直到把src数组中的末尾的'\0'拷贝过来时才结束,并且返回dest数组首字符的地址,打印的结果为:neymarjr。
对于strcpy函数的相关参数,可以参考下图:

首先strcpy的返回类型为一个char*的指针,这个指针指向的是destination的起始位置,对于strcpy的形参部分,一个是要拷贝的目的地的指针,另一个则是要拷贝的字符串的指针。例如上面的代码,src数组里的字符串”neymarjr“会被拷贝到dest数组里。
模拟实现:
对于strcpy函数的模拟实现,这里简单的介绍一下,比如下图:

首先我们要保证返回的是dest的首元素地址,那么我们需要一个指针变量来储存起始地址,最后返回的也是这个指针变量,接下来就是一个字节一个字节的拷贝,用while循环,并且判断条件为(*dest++ = *src++),因为是后置++,那么先使用*dest = *src,此时表达式的值为*dest的值,即为用来判断的值,判断完之后再进行指针的+1。
补充(注意):
这里把src数组里的字符串”neymarjr“拷贝到dest数组里时,从dest数组的首元素开始拷贝,同时也会把src数组字符串末尾的'\0'拷贝过去,并且dest数组要保证足够大,防止溢出现象。
3.strcat函数的使用以及模拟实现
功能:
strcat是把源字符串的内容拷贝到目标字符串的后面,即是从目的字符串末尾的'\0'把源字符串拷贝到后面。
使用:
使用strcat库函数要包括头文件#include <string.h>,使用strcat,例如下图:

使用strcat函数,把src里的字符串内容"neymarjr"拷贝到dest里的字符串"abcdef"后面,strcat它会返回目标字符串的地址,打印得到的结果为"abcdefneymarjr"。
对于strcat函数相关的参数,可参考下图:

首先strcat函数会返回一个char*的指针,这个指针所指向的位置为destination的起始位置,接着形参部分,第一个char*指针用于接收目标字符串的首字符地址,第二个char*指针是用于接收源字符串的首字符地址。
模拟实现:
对于strcat函数的模拟实现,可如下图:

补充(注意):
strcat进行字符串拼接的过程中,目标字符串必须要有'\0'才行,因为strcat拼接字符串是从目标字符串'\0'的位置进行拼接的,同时源字符串也必须包含'\0',拼接目标字符串时是把'\0'之前的字符串拼接过去,不包括'\0',拼接完成后要在目标字符串的末尾补上'\0'。
4.strcmp函数的使用和模拟实现
功能:
strcmp函数是用于比较字符串大小的函数。
使用:
使用strcmp得包含头文件#include <string.h>,使用如图:

使用strcmp比较字符串“ney”和“mes”的大小(实际比的是ASCII值),例如上面,字符n的ASCII值大于m的ASCII值,故strcmp返回一个大于0的整数。
对于strcmp函数相关的参数,可参考下图:

对于strcmp的返回值为int类型,即如果arr1 > arr2 ,函数会返回一个大于0的整数,如果arr1 < arr2 ,函数会返回一个小于0的整数,当字符串相等时会返回0;接着是形参的部分,两个参数都是字符串的地址,并且要用const限制字符串不被修改。
模拟实现:
对于strcmp函数的模拟实现,如下图:

补充(注意):
strcmp比较两个字符串的大小不是看其长度,是看字符串对应的ASCII值大小进行比较。
5.strstr函数的使用和模拟实现
功能:
strstr函数是用于在一个字符串中查找另一个字符串是否存在。
使用:
使用strstr函数也必须包含头文件#include <string.h>,对于strstr函数的使用,如下图:

我们定义了字符串“abbbbabcd”和字符串“abc”,使用strstr函数,即在“abbbbabcd”中寻找“abc”,并且返回在arr1中找到的字符串的地址。
模拟实现:
对于strstr函数
的模拟实现,如下图:

二 . 内存函数
1.memcpy函数的使用以及模拟实现
功能:
memcpy函数是把source的位置开始向后复制n个字节到destination所指向的内存位置。
使用:
使用memcpy函数,需要包含头文件#include <string.h>,对于memcpy函数的使用,如下图:

使用memcpy,把在source位置开始的内容,复制到destination所指向内存的位置中,并且这里复制是以字节为单位,如上图是把source位置的5*sizeof(int)个字节的内容复制过去。
对于memcpy函数的参数,可参考下图:

首先memcpy函数针对的类型可以用为很多种,所以它的返回类型为void*的指针,并且这个指针是指向destination所在的起始位置,对于形参部分,首先是指向复制的目的地其实位置的destination,其次是指向被拷贝内容的起始位置source,最后是需要拷贝多少个字节的num。
模拟实现:
对于memcpy函数的模拟实现,比如下图:

对于memcpy函数,本质上它是不能处理重叠内存的,但是对于vs2022来说,内存函数memcpy是具有处理重叠内存的能力,但实际上对于这种情况,是交给memmove去处理的。
补充(注意):
memcpy函数针对的是多种类型的字节拷贝,并且是针对字节为单位的,这个函数遇到'\0'是不会停下来的,对于内存重叠的情况,我们默认memcpy函数是处理不了的。
2.memmove函数的使用以及模拟实现
功能:
针对memcpy函数,其区别在于memmove可以处理内存重叠的情况,即原空间和目标空间出现重叠时,可以使用memmove函数。
使用:
对于memmove函数的使用,我们需要包含头文件#include <string.h>,对于其使用,如下图:

对于memmove函数,我们是把arr(数组名为首元素地址)所指向的5*sizeof(int)个字节的内容复制到arr+2所指向的内存位置。
对于memmove函数的参数部分,可参考下图:

memmove函数会返回一个void*的指针,并且指针指向的位置为指针void*destinaton所指向的内存位置,void*destination为目标空间的起始地址,const void*source为原空间的起始地址,并且其内容不可修改,最后是需要拷贝的字节数num。
模拟实现:
对于memmove函数的模拟实现,如下图:

对于memmove函数的模拟实现,这里要注意一下就是des和src的位置不同,所用的拷贝方式也是不同的,比如上面的当des < src时,我们需要采用从前向后拷贝的方式,而对于dest >= src时,我们则采用从后向前拷贝。
补充(注意):
对于memmove函数,它与memcpy的区别在于memmove函数能处理这种内存重叠的问题,还有一点就是memmove函数的返回值为指针,并且这个指针不一定指向的是目标内存的起始地址,就如上面的,它返回的地址是arr+2的地址,而不是起始地址。
最后:
对于上述的字符串函数strcpy,strcat,strcmp函数,它们还有对应的strncpy,strncat,strncmp函数,其区别在于后者能限制其大小。
对于上诉的库函数的说明,如果有错的地方请各位帮忙指出,谢谢各位!

1722

被折叠的 条评论
为什么被折叠?



