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

Posted 麋璐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat相关的知识,希望对你有一定的参考价值。

       我们在学习编程语言的过程中,会学习很多库函数,这些库函数也帮助我们解决了很多复杂的问题。今天我要给大家带来的就是深度剖析我们平常所使用的库函数。

       首先我们要说明的,当我们要去模拟实现这些库函数的时候,我们必须了解这些库函数的用法,参数以及返回值还有注意事项,有不懂的库函数我们可以去查看一些较为专业的网站,像CSDN,我们还可以去使用软件,MSDN等先了解这些库函数的用法。

       就比如,当我么你要去了解memcpy时,我们可以在MSDN中的索引搜索,

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

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

模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat_i++_02

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

模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat_字符串_03

我们要留意下方的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 = (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种情况,下面我将画图说明:

模拟实现库函数strlen,strcpy,strstr,memmove,memcpy,strcat_赋值_04

重点在第一个图,当我们正向赋值时,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 = (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的主要内容,如果未能解决你的问题,请参考以下文章

C语言初阶笔记程序员必须要会的实用调试技巧(含库函数strcpy和strlen的模拟实现)!!

C语言初阶笔记程序员必须要会的实用调试技巧(含库函数strcpy和strlen的模拟实现)!!

C语言初阶笔记程序员必须要会的实用调试技巧(含库函数strcpy和strlen的模拟实现)!!

一些字符和字符串库函数操作模拟实现

常用的字符串函数详解

字符串函数的使用与模拟实现