当前位置: 代码迷 >> 综合 >> 模拟实现strlen,strcpy,strcmp,strstr,strcat,memcpy,memmove,memset
  详细解决方案

模拟实现strlen,strcpy,strcmp,strstr,strcat,memcpy,memmove,memset

热度:31   发布时间:2023-12-01 01:56:45.0

strlen


实现的方法:使用 指针-指针 算出之间的差值,也就是这个字符串的真实长度(指针-指针的要求就是:两个指针是同一个类型)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>int My_Strlen(char *p)
{char *p1 = p;while( *p1 != '\0' ){*p1++;}/*while(*(++p1)){;}*/return p1-p;
}void testMy_strlen()
{char *p = "1234";printf("%d\n",My_Strlen(p));
}

strcpy


功能:字符串拷贝,把源字符串src,拷贝到目标空间dest中实现过程:1. 目标空间( dest )足够大,足够容得下src字符串(包括\02. 目标字符串可修改,源字符串不能修改(类型前加const)3. 模拟实现strcpy返回值类型是char*,有返回值为了实现链式访问4. 把src中内容拷贝到dest中,直到src的'\0'拷贝过去结束
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>char* my_strcpy( char *dest,const char *src )
{char *ret = dest;assert(dest!=NULL);assert(src!=NULL);while( *ret++ = *src++ ) // 相当于 while( (*ret++ = *src) != '\0' ){;}return dest;
}void testMy_strcpy()
{char p1[20] = "abcd"; // dest(目标空间)char *p2 = "efghi";   // src(源字符串)my_strcpy(p1,p2);// strcpy(p1,p2); 库函数的用法printf("%s\n",p1);printf("%d\n",strlen(my_strcpy(p1,p2)));
}

运行结果:

这里写图片描述

strcat


功能:字符串追加,把源字符串src,追加到目标空间dest中实现过程:1. 目标空间( dest )足够大,足够容得下追加的src字符串(包括\02. 目标字符串可修改,源字符串不能修改(类型前加const)3.模拟实现strcat返回值类型是char*,有返回值为了实现链式访问4. 过程:首先要找目标空间dest中'\0',并且让源字符串src覆盖dest中'\0',然后开始追加,直到追加到src的'\0'结束  显然:strcat不能实现自己给自己追加,因为刚开始追加的时候,已经把'\0'覆盖,后面再去追加时(结束条件是:遇到'\0'),所以是无法实现的
char* My_Strcat(char *dest,const char *src)
{char *ret = dest;assert(dest && src);while( *dest != '\0' ) {*dest++;}while( *dest++ = *src++ ){;}return ret;
}void testMy_strcat()
{char p1[20] = "abcd ";char *p2 = "efgh";// strcat(p1,p2); 库函数用法——p1是目标空间,p2是源字符串My_Strcat(p1,p2);printf("%s\n",p1);
}

运行结果:

这里写图片描述

strcmp


功能:字符串比较函数实现过程:1. 首先s1和s2是固定字符串,要实现的是比较,所以都不能被修改因此必须加上const 修饰2. 先判断两个字符串长度是否相等,如果不相等,就没有必要再去遍历,直接返回-13. 如果相等:一起遍历字符串,首先比较第一个字符:1. 两个字符的ASCII码值如果不相等,直接返回-12. 两个字符的ASCII码值相等,继续遍历3. 直到遍历遇到'\0',结束遍历
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>int My_Strcmp(const char *dest,const char *src)
{int len1 = strlen(dest);int len2 = strlen(src);if( len1 != len2 )return -1;else{while( *dest && *src ){if( *dest == *src ){*dest++ ;*src++ ;}elsereturn -1;}return 0;}
}void testMy_strcmp()
{char *p1 = "hell0";  // 这里是零,结果比较就是不相等的char *p2 = "hello";int flag = My_Strcmp(p1,p2);if( flag == 0 ){printf("两个字符串相等\n");}else{printf("两个字符串不相等\n");}
}

运行结果:

这里写图片描述

strstr


功能:在字符串中查找子串,如果找到,输出第一次找到子串的开始位置实现过程:1. 首先str和substr是固定字符串,要实现的是查找,所以都不能被修改因此必须加上const 修饰2. 要考虑到多种情况如下1."abcdef"中找"bcd"         返回b的地址,输出bcdef2."abcdef"中找""(空字符串)  没有必要找,直接把abcdef输出3.“abcbcd”中找"bcd"       开始找str中b和substr中b相同,继续向后发现b和c不同,这时substr应当退回去,从str中刚才开始匹配的下一个元素开始重新匹配,也就是str第三个元素开始继续匹配,如此重复,直到匹配成功。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>char* My_Strstr( const char *str, const char *substr )
{char *cp = (char *)str;char *cur1 = (char *)str;char *cur2 = (char *)substr;assert(str);if( *substr == '\0' )return cp;while( *cp ){// cp是保存之前str的位置,cur1用来遍历的去比较字符串,// 万一没有匹配成功,cp++,重新开始匹配cur1 = cp;cur2 = (char *)substr;while( *cur1 && *cur2 && (*cur1 == *cur2) ){*cur1++;*cur2++;}if( *cur2 == '\0' )return cp;*cp++;}return NULL;
}void testMy_strstr()
{char *p1 = "abcdbcd";char *p2 = "";printf("%s\n",My_Strstr(p1,p2));
}

运行结果:

这里写图片描述

char *p1 = "abcdbcd";
char *p2 = "bcd";

这里写图片描述

memcpy


功能:由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。    (src和dest内存不重叠)  memcpystrcpy 的区别:原型:void *memcpy(void *memTo,const void *memFrom,size_t size)
char *strcpy(char *dst,const char *src);相同点:strcpymemcpy都可以实现拷贝的功能不同点:1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容, 例如字符数组、整型、结构体、类等。2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,  所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy4、实现功能不同,strcpy主要实现字符串变量间的拷贝,memcpy主要是内存块间的拷贝。5、操作对象不同,strcpy的操作对象是字符串,memcpy 的操作对象是内存地址,并不限于何种数据类型。6、执行效率不同,memcpy最高,strcpy次之。
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void *my_memcpy(void*dest, void*src, size_t n)
{char *p = (char *)dest;const char *p1 = (const char *)src;assert(dest && src);while(n--){*p++ = *p1++;}return dest;
}
void testMy_Memcpy()
{char p1[20] = "abc";char *p2 = "abcdefg";// 库函数:memcpy(p1, p2, 5);my_memcpy(p1,p2,5);printf("%s\n",p1);//int p1[20] = {1,2,3};//int p2[6] = {1,2,3,4,5,6};// // 库函数:memcpy(p1, p2, 30); // 第三个参数是按照字节算的//my_memcpy(p1,p2,30);//printf("%d\n",p1[5]);
}

memmove


功能:由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。(src和dest内存重叠)注意: 不重叠部分:从前向后拷贝重叠部分:从后向前拷贝
#include<stdlib.h>
#include<string.h>
#include<assert.h>void * my_memmove( void *dest, const void * src, size_t count )
{void * ret = dest;if( dest <= src || (char *)dest >= (char *)src+count ){while( count-- ){*(char *)dest = *(char *)src;dest = (char *)dest + 1;src = (char *)src + 1;}}else{dest = (char *)dest + count-1;src = (char *)src + count -1;while(count--){*(char *)dest = *(char *)src;dest = (char *)dest -1;src = (char *)src -1;}}return ret;
}void testMy_Memmove()
{char p[] = "abcdefgh";// 库函数:memmove(p,p+2,7);my_memmove(p,p+3,5);printf("%s\n",p);
}

memset


功能: 将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值1. 第一个参数为指定内存地址 2. 块的大小由第三个参数指定3. 这个函数通常为新申请的内存做初始化工作,其返回值为指向s的指针

void * my_memset(void*s, int ch, size_t n)
{assert(s);char *ret = (char *)s;while (n--){*ret++ =(char) ch;}return s;
}
int main()
{char arr[10];int i;my_memset(arr, 0, 10*sizeof(char));for (i = 0; i < 10; i++){printf("%d\n", arr[i]);}system("pause");return 0;
}