用C语言模拟实现str和mem相关函数

>str开头的函数只能用于字符数据的操作,遇到NULL'\0'会停止。

>mem开头的函数用于操作内存内容,可以处理NULL.操作的基本单位是字节操作

1.str和mem对比实例:

例如:strcpy和memcpy操作:

>模拟strcpy:

#include<stdio.h>
#include<assert.h>
#include<windows.h> 
char *my_strcpy(char *dest, const char *str)
{
	assert(dest);
	assert(str);
	while (*dest = *str){
		dest++;
		str++;
	}
	return dest;
}

int main (){
	char *p="abcdefg";
	char q[20];    //这里q是可变char数组,不能定义为char *类型
	my_strcpy(q,p);
	printf("%s",q);
	system("pause");
	return 0;
} 

>模拟memcpy:

方法一:通过ascll码表的位置,进行字符的差运算。

#include<stdio.h>
#include<Windows.h>
void my_memcpy(void *str1,const void *str2,size_t size)
{    //void类型不能定义变量,void是无类型,不能确定内存的大小,但是void*可以定义,因为指针大小为4,但不能解引用,因为引用后为void
	void *ret = str1;
	while (size--){
		*(char *)str1 = *(char *)str2;
		str1=(char *)str1+1;
		str2=(char *)str2+1;
	}

}
int main(){
	char c[50] = "abcdefgh";
	int size = 3;
	my_memcpy(c+1, c, size);
	printf("%s", c);
	system("pause");
	return 0;
}

这里会出现内存重叠问题,比如上例中本来的预期结果是:aabcefgh可是运行结果为:aaaaefgh。

对于memcpy总结下面四种出现的情况:以字符串为例。

void my_memcpy(void *dest,const void *src,size_t size)//src要拷贝的字符串,dest目的字符串


在上面四种情况中:(1),(2),(3)拷贝的时候从前往后拷,不会出现覆盖问题。(4)情况拷贝的时候必须从后往前拷,如果从前往后会出现从开始的那个字符其,到要拷贝的长度这段字符串会一直被覆盖。

下面是针对第四种情况:

#include<stdio.h>
#include<Windows.h>
void my_memcpy(void *dest,const void *src,size_t size)
{
	void *ret = dest;
	if (dest<=src||(char *)dest>=((char *)src+size)){
		while (size--){
			*(char *)dest = *(char *)src;
			dest = (char *)dest + 1;
			src = (char *)src + 1;
		}
	}
	else{
		dest = (char *)dest+size - 1;
		src = (char *)src+size - 1;
		while (size--){
			*(char *)dest = *(char *)src;
			dest = (char *)dest - 1;
			src = (char *)src -1;
		}
	}

}
int main(){
	char c[50] = "abcdefgh";
	int size = 3;
	my_memcpy(c+1, c, size);
	printf("%s", c);
	system("pause");
	return 0;
}

那么运行结果就是:aabcdefgh。

总结strcpy和memcpy的区别:

1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

2.模拟实现strlen:

>直接用计数器实现:

#include<stdio.h>
#include<Windows.h>
int my_strlen(const char *str)
{
	int count = 0;
	while (*str){
		count++;
		str++;
	}
	return count;
}
int main(){
	char *p= "abcdef";
	int ret = my_strlen(p);
	printf("%d\n", ret);
	system("pause");
	return 0;
}

>不创建临时变量的计数器:通过递归

#include<stdio.h>
#include<Windows.h>
int my_strlen(const char *str)
{
	if (*str=='\0'){
		return 0;
	}
	else 
		return 1 + my_strlen(str + 1);
}
int main(){
	char *p= "abcdef";
	int ret = my_strlen(p);
	printf("%d\n", ret);
	system("pause");
	return 0;
}

>指针-指针:

#include<stdio.h>
#include<Windows.h>
int my_strlen(const char *str)
{
	char *p = str;     //p指向首元素
	while (*p != '\0'){
		p++;
	}
	return p - str;
}
int main(){
	char *p= "abcdef";
	int ret = my_strlen(p);
	printf("%d\n", ret);
	system("pause");
	return 0;

>不用if等判断语句和循环语句;

#include<stdio.h>
#include<Windows.h>
int my_strlen(const char *str)
{
	
	return *str ? (1 + my_strlen(str + 1)) : 0;
}
int main(){
	char *p = "abcdef";
	int ret = my_strlen(p);
	printf("%d\n", ret);
	system("pause");
	return 0;
}

3.模拟实现strcat:

思路:先使被拼接的字符串(dest)指向'\0',然后将要拼接的字符串(str)依次拷贝到dest后

#include<stdio.h>
#include<Windows.h>
#include<assert.h>
char *my_strcat(char *dest, const char *str)
{
	char *ret =dest;
	assert(dest);
	assert(str);
	while (*dest){
		dest++;
	}
	while (*dest = *str){
		dest++;
		str++;
	}
	return ret;
}
int main(){
	char *str = "abcdef";
	char p[30] = "xyz";
	char *ret=my_strcat(p, str);
	printf("%s", ret);
	system("pause");
	return 0;
}

4.模拟实现strstr:

思路:在str1中查找str2并返回,str1中str2所在字符串之后的所有字符串。定义一个指针变量s指向str1,然后s与str2中的字符进行比较,如果一直比较到'\0'那么就返回str1,如果比较遇到不相等,则s指向str1的第二个字符重新开始比较。

#include<stdio.h>
#include<windows.h>
#include<assert.h>
char *my_strstr(char *str1, const char *str2)
{
	assert(str1);
	assert(str2);
	char *p = (char*)str1;
	char *q = (char *)str2;
	char *s = NULL;
	while (*p){
		s = p;
		q = str2;
		while (*s&&*q && (*s == *q)){
			s++;
			q++;
		}
		if (*q == '\0')
			return p;
		p++;
	}
	return 0;
}
int main(){
	char *str1 = "abcdefg";
	char *str2 = "de";
	char *p = my_strstr(str1, str2);
	printf("%s", p);
	system("pause");
	return 0;
}

运行结果:defg

5.模拟实现strcpy:

思路:通过字符在ASCLL表中的位置序号进行差运算比较。

比较的是ASCLL中的位置:如abcg小于abcz

#include<stdio.h>
#include<Windows.h>
int my_strcmp(const char *str1,const char *str2)
{
	int ret = 0;
	while ((!(ret = *(unsigned char*)str1 - *(unsigned char*)str2)&&str1))   //一相等为基础
 {
		str1++;
		str2++;
	}
	if (ret > 0)
		ret = 1;
	else if (ret<0)
		ret = -1;
	return (ret);
}
int main(){
	char *str1 = "abcd";
	char *str2 = "abcdg";
	int ret = 0;
	ret = my_strcmp(str1, str2);
	if (ret==1)
		printf("str1大于str2\n");
	if (ret==-1)
		printf("str1小于str2\n");
	if (ret==0)
		printf("str1等于str2\n");
	system("pause");
	return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_41889292/article/details/80342146