函数的模拟实现


通过本次对库函数的模拟实现,提升了代码能力的同时也加深了对这些库函数的理解,为今后的学习过程中的快捷使用打下了基础

📘模拟实现strlen

💦cplusplus中strlen是这样的
在这里插入图片描述

#include<assert.h>
#include<stdio.h>
size_t my_strlen(const char* str)
{
	assert(str);
	const char* start = str;
	const char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;
}

int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

💦运行结果:
在这里插入图片描述

💡strlen遇到’\0’停止,如果字符数组中没有’\0’,运行程序后最后的值就是一个随机值,在使用时要注意’0’这个特殊的元素

📘模拟实现strcpy

💦cplusplus中strcpy是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest);
	assert(src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}

	return ret;
}
int main()
{
	char arr1[20] = "abc";
	char arr2[] =   "hello bit";

	printf("%s\n", my_strcpy(arr1, arr2));

	return 0;
}

💦运行结果:
在这里插入图片描述
💡在这个函数中我们没有动态开辟内存,所以在将arr2复制到arr1里面去的时候要注意arr1的大小要大于arr2,虽然我们看到例子中也能正常拷贝,但是还是要尽量避免这样的错误
💡同样如果arr1中是一个常量字符串的话,也不能进行正常拷贝,p 的确指向其地址,但该地址存在于在进程的 text 段,text 段除了保存常量还保存可执行代码,因此是不允许可写权限的,而是只允许可读、可执行权限

在这里插入图片描述

📘模拟实现strncpy

💦cplusplus中strncpy是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<assert.h>
#include<stdio.h>
char* strncpy(char* destination, const char* source, size_t num)
{
	assert(destination);
	assert(source);
	char* ret = destination;
	while (num--)
	{
		*destination++ = *source++;
	}
	return ret;
}
int main()
{
	char str1[] = "abcdefghi";
	char str2[] = "xxxx";
	printf("%s", strncpy(str1, str2, 2));
	return 0;
}

运行结果:

在这里插入图片描述

📘模拟实现strcmp

💦cplusplus中strcmp是这样的
在这里插入图片描述

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	return *s1 - *s2;
}

int main()
{
	char arr1[] = "abc";
	char arr2[] = "abc";
	int ret = my_strcmp(arr1, arr2);
	if (ret < 0)
		printf("arr1<arr2\n");
	else if(ret>0)
		printf("arr1>arr2\n");
	else
		printf("arr1==arr2\n");

	printf("%d\n", ret);

	return 0;
}

💦运行结果:
在这里插入图片描述

📘模拟实现strcat

💦cplusplus中strcat是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
char* my_strcat(char* dest, const char*src)
{
	//1.找目标空间中的\0
	char* cur = dest;
	while (*cur)
	{
		cur++;
	}
	//2.拷贝源头数据到\0之后的空间
	while (*cur++ = *src++)
	{
		;
	}

	return dest;
}

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world!";
	printf("%s\n", my_strcat(arr1, arr2));

	return 0;
}

💦运行结果:
在这里插入图片描述
💡这个与strlen相似,要求arr1中要有’\0’,同时也要满足arr1的大小比arr2大

📘模拟实现strncat

💦cplusplus中strncat是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
char* strncat(char* destination, const char* source, size_t num)
{
	char* cur = destination;
	while (*cur)
	{
		cur++;
	}
	while (num--)
	{
		*cur++ = *source++;
	}
	*cur = '\0';
	return destination;
}
int main()
{
	char str1[20] = "hello ";
	char str2[] = "world !!!";
	printf("%s", strncat(str1, str2, 7));
	return 0;
}

运行结果:
在这里插入图片描述

📘模拟实现strstr

💦cplusplus中strstr是这样的
在这里插入图片描述
1、暴力求解

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = str1;
	const char* s2 = str2;
	const char* p = str1;
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (*s1!='\0' && *s2!='\0' && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)p;//找到了
		}
		p++;
	}
	return NULL;//找不到子串
}
int main()
{
	char arr1[] = "abcdefabcdef";
	char arr2[] = "cdq";

	char* p = my_strstr(arr1, arr2);
	if (p == NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}

💦运行结果:
在这里插入图片描述
2、KMP算法

📘模拟实现memset

💦cplusplus中memset是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memset(void* ptr, int value, size_t num)
{
	void* p = ptr;
	assert(ptr);
	while (num--)
	{
		*(char*)ptr = value;
		ptr = (char*)ptr + 1;
	}
	return p;
}
int main()
{
	char arr1[] = "1234568";
	my_memset(arr1, 'a', 4);
	printf("%s", arr1);
	return 0;
}

💦运行结果:
在这里插入图片描述
💡特别注意size_t num指的是从起始地址开始的字节数,在对非字符数组使用这个函数的时候要特别注意
在这里插入图片描述

📘模拟实现memcpy

memcpy只需要实现不重叠的拷贝就可以了 - 60分,但在vs测试中我们发现可以达到 100分
💦cplusplus中memcpy是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include<stdio.h>

void* my_memcpy(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest);
	assert(src);

	while(num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}

	return ret;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

💦运行结果:
在这里插入图片描述
💡memcpy可以说是strcpy的进阶版了,可以用于各种类型的数据的拷贝,注意事项与strcpy相似

📘模拟实现memmove

memmove是需要实现重叠内存的拷贝的(100)
💦cplusplus中memmove是这样的

在这里插入图片描述
💡memmove可以说是memcpy的进阶版了,可以用于各种类型的数据的拷贝,同时还可以实现重叠内存的一个拷贝,注意事项与strcpy相似

#define _CRT_SECURE_NO_WARNINGS
#include<assert.h>
#include<stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest);
	assert(src);

	if (dest < src)//1 前->后
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else //2 3 后->前
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1+2, arr1, 20);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

💦运行结果:
在这里插入图片描述

📘模拟实现qsort

💦cplusplus中qsort是这样的
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//qsort 可以排序任意类型的数据
//void qsort(void* base, //待排序数据的起始地址
//	       size_t num,   //待排序数据的元素个数
//	       size_t size,  //待排序数据元素的大小(单位是字节)
//	       int (*cmp)(const void*, const void*) //比较2个元素大小的函数指针
//          );
//

void print(float arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%lf ", arr[i]);
	}
	printf("\n");
}
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void my_qsort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}
//测试qsort函数排序整型数据

void test1()
{
	int arr[] = { 2,1,3,7,5,9,6,8,0,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);
}
//测试qsort函数排序浮点型数据
void test2()
{
	float arr[] = { 2.0f,1.0f,3.0f,7.0f,5.0f,9.0f,6.0f,8.0f,4.0f };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);
}

struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

//测试qsort排序结构体数据
void test3()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 55}, {"wangwu", 40} };
	int sz = sizeof(s) / sizeof(s[0]);
	my_qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	my_qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);

}

int main()
{
	test1();
	test2();
	test3();

	return 0;
}

💦运行结果:
在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
在C语言中,我们可以模拟实现memcpy函数。memcpy函数的原型为void * memcpy(void * destination, const void * source, size_t num),它的作用是将源地址(source)指向的内存块的数据拷贝到目标地址(destination)指向的内存块中,拷贝的字节数由第三个参数num指定。 要实现memcpy函数,我们可以按照以下步骤进行操作: 1. 首先,我们需要创建一个与源内存块相同大小的目标内存块,并将目标内存块的地址保存在destination指针中。 2. 接下来,我们使用一个循环来逐字节地将源内存块的数据复制到目标内存块中,直到拷贝的字节数达到了num的值。 3. 最后,我们返回目标内存块的地址(destination指针),作为函数的返回值。 下面是一个示例的实现代码: ```c void *my_memcpy(void *destination, const void *source, size_t num) { char *dest = (char *)destination; const char *src = (const char *)source; for (size_t i = 0; i < num; i++) { dest[i = src[i]; } return destination; } ``` 在这个实现中,我们将destination和source指针都转换为char类型的指针,这样可以逐字节地进行数据拷贝。然后,我们使用一个循环来逐字节地将源内存块的数据复制到目标内存块中,直到拷贝的字节数达到了num的值。最后,我们返回目标内存块的地址作为函数的返回值。 这样,我们就实现了一个简单的memcpy函数模拟实现。需要注意的是,这只是一个简单的示例实现,实际的memcpy函数可能会有更复杂的实现方式,具体实现可能因编译器和操作系统的不同而有所差异。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr Maria

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值