模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat

一年好景君须记,最是橙黄橘绿时。这篇文章主要讲述模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat相关的知识,希望能为你提供帮助。
        我们在学习编程语言的过程中,会学习很多库函数,这些库函数也帮助我们解决了很多复杂的问题。今天我要给大家带来的就是深度剖析我们平常所使用的库函数。
        首先我们要说明的,当我们要去模拟实现这些库函数的时候,我们必须了解这些库函数的用法,参数以及返回值还有注意事项,有不懂的库函数我们可以去查看一些较为专业的网站,像CSDN,我们还可以去使用软件,MSDN等先了解这些库函数的用法。
        就比如,当我么你要去了解memcpy时,我们可以在MSDN中的索引搜索,

右边就是你想要的函数的全部信息

其次我们还要去看下面的注释

我们要留意下方的remarks,这里会告诉我们这个函数的注意事项。
接下来我们来书写库函数的代码,简单的我会只给出代码,每个代码我都会给出相应的注意事项(我给出的代码并没有引头文件,要使用的朋友,需要自己引入头文件)
1.模拟实现strlen
size_t my_strlen(const char *string)
{
assert(string != NULL);
size_t count = 0;
while (*string)
{
count++;
string++;
}
return count;
}
int main()
{
char arr[] = "abcdefghi";
size_t ret = my_strlen(arr);
printf("ret=%d", ret);
return 0;
}
这个代码还是比较简单的,就是计算字符串的长度,治理要注意的是断言,assert的使用,当我们string接收的指针为NULL时,代码会报错,停止走动。
2.模拟实现strcpy
char* my_strcpy(char *Dest, const char *Sou)
{
assert(Dest != NULL);
assert(Sou != NULL);
char* tmp = Dest;
while (*Sou)
{
*tmp++ = *Sou++;
}
*tmp = *Sou;
return Dest;
}
int main()
{
char arr1[20] = "abcdefg";
char arr2[] = "bbbbbbbbbbbb";
char* ret = my_strcpy(arr1, arr2);
printf("%s", ret);
return 0;
}
这个代码要注意的就是arr1的大小必须大于两个字符串的最大值,要不然代码可以走通,但在调试的时候,会出现奔溃的情况,原因就是,arr1开辟的空间太小,导致越界访问,而Sou的类型const主要是保护Sou,使它无法被改变,接着就是assert断言。
3.模拟实现strstr
char* my_strstr(const char *string, const char *strCharSet)
{
assert(string != NULL);
assert(strCharSet != NULL);
char* ar1 = (char*)string;
char* ar2 = (char*)strCharSet;
int i = 0;
int j = 0;
if (ar2[i] == \\0)
return NULL;
while (ar1[i]!=\\0)
{
while (ar1[i]& & ar2[j])
{
if (ar1[i] == ar2[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
}
if (ar2[j] == \\0)
return (char*)string;
return NULL;
}
}
int main()
{
char arr1[] = "ABCDEFGABCDH";
char arr2[] = "FGABC";
char* tmp = my_strstr(arr1, arr2);
if (tmp != NULL)
{
printf("是子链");
}
else
{
printf("不是子链");
}
return 0;
}
strstr函数的用法是判断arr2是不是arr1的子链,也就是是不是子集;这里我使用的是”暴力求解法“,就是判断arr1的每一个字母去匹配arr2的首字母,只有第一个判断成功,才能去判断arr2的第二个字母是否匹配,会循环很多次,效率非常的低。有一种高效的方法,叫做KMP算法,可以高效的解决这类问题,但是算法非常的复杂,感兴趣的朋友可以去试试。
4.模拟实现memmove
void* my_memmove(void *dest, const void *src, size_t count)
{
assert(dest != NULL);
assert(src != NULL);
char* pdest = (char*)dest;
const char* psrc = https://www.songbingjia.com/android/(const char*)src;
if (pdest > psrc)
{
while (count)
{
*(pdest + count-1) = *(psrc + count-1);
count--;
}
}
else
{
while (count)
{
*pdest = *psrc;
pdest++;
psrc++;
count--;
}
}
return dest;
}
int main()
{
char arr[10] = "abcdefg";
my_memmove(arr+2, arr , 2);
int i = 0;
for (i = 0; i < 7; i++)
{
printf("%c ", arr[i]);
}
return 0;
}
memmove这个函数就是将一个字符串的几个字符平移,我们在模拟时,着重要注意的是内存重叠的问题,在使用这个字符的时候我们会遇到5种情况,下面我将画图说明:

重点在第一个图,当我们正向赋值时,ab会先赋给cd,结果就会变成abababg,所以这时我们需要反向赋值,就能很好的解决这个问题。
5.模拟实现memcpy
void* my_memmove(void *dest, const void *src, size_t count)
{
assert(dest != NULL);
assert(src != NULL);
char* pdest = (char*)dest;
const char* psrc = https://www.songbingjia.com/android/(const char*)src;
while (count != 0)
{
*pdest++ = *psrc++;
count--;
}
return dest;
}
int main()
{
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = { 0 };
my_memmove(arr2, arr1, sizeof(int)*10);
int i = 0;
for (i = 0; i < 10 ; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
memcpy函数的作用和strcpy的作用一样,都是将一个字符串复制给另一个字符串;但是memcpy函数是将一个函数字符串的整个地址赋值改变,以char为单位(1字节),所以使用起来正确率和精准度更高。
6.模拟实现strcat
char* my_strcat(char *Dest, const char *Sou)
{
assert(Dest != NULL);
assert(Sou != NULL);
char* dest = Dest;
while (*dest)
{
dest++;
}
while (*Sou)
{
*dest++ = *Sou++;
}
dest = \\0;
return Dest;
}
int main()
{
char arr1[20] = "abcdefg";
char arr2[] = "higkl";
char* tmp = my_strcat(arr1, arr2);
printf("%s", tmp);
return 0;
}
strcat函数的意思就是将arr1和arr2相连接,其中要注意的就是arr1的空间不得少于arr1+arr2的和,最后还是要赋值\\0。
【模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat】以上就是我这次模拟实现的代码,如有不足,希望大家可以积极批评指正。

    推荐阅读