函数的模拟实现


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

📘模拟实现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;
}

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

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr Maria

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

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

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

打赏作者

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

抵扣说明:

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

余额充值