【C语言】库函数及内存函数的模拟实现

1.strlen 的模拟实现

//方法一:计数器
//用count计数,记录parr不等于'\0'之前的一共跑了几次,就是字符串的长度
int my_strlen(char* parr)
{
	assert(parr);
	int count = 0;
	while (*parr)
	{
		parr++;
		count++;
	}
	return count;
}

//方法二:指针相减
//相同类型的指针相减,得数是两个指针之间的元素个数
int my_strlen(char* parr)
{
	assert(parr);
	char* ret = parr;
	while (*parr)
	{
		parr++;
	}
	return parr - ret;
}

2.strcpy的模拟实现

//++优先级大于解引用*,且后置++先使用再++,所以在while循环的判断中,先将parr2赋值给parr1
//后,再解引用,然后将+1后的parr2再次赋值给parr1后,进行解引用,以此类推
//直到parr2指向'\0',赋值给parr1,两者均为'\0',跳出循环;
char* my_strcpy(char* parr1, const char* parr2)
{
	assert(parr1 && parr2);
	char* ret = parr1;
	while (*parr1++=*parr2++)
	{
		;
	}
	return ret;
}

3.strcat的模拟实现

strcat是字符串追加函数,是在一个字符串后再继续追加想要添加的字符串,模拟代码如下:

//先找到被追加的字符串的'\0'
//从该位置开始加入需要添加的字符串parr2;
char* my_strcat(char* parr1, const char* parr2)
{
	assert(parr1 && parr2);
	char* ret = parr1;
	while (*parr1)
	{
		parr1++;
	}
	while (*parr2)
	{
		*parr1++ = *parr2++;
	}
	return ret;
}

4.strcmp的模拟实现

//strcmp函数,比较的是字符的ASCII码值,parr1比parr2大,返回正值,小返回负值,等于返回0;
int my_strcmp(const char* parr1, const char* parr2)
{
	assert(parr1 && parr2);
	while (*parr1==*parr2)
	{
		if (*parr1 == '\0'||*parr2=='\0')
		{
			return 0;
		}
		parr1++;
		parr2++;
	}
	return *parr1 - *parr2;
}

5.strncpy的模拟实现

char *strncpy(char *dest, const char *src, size_t n)

strncpy把源字符串的字符复制到目标数组。然而,它总是正好向dest写入n个字符。如果strlen(src)的值小于n,dst数组就用额外的NUL字节填充到len长度,如果strlen(src)的值大于或等于len,那么只有len个字符被复制到dst中。”注意!它的结果将不会以NUL字节结尾。(NUL即‘\0’).

即:如果parr1一开始未被初始化成0,则必须手动添加'\0'

//也就是说,通过对比parr2的长度和num的大小,判断以什么作为循环的标准;
char* my_strncpy(char* parr1, const char* parr2,size_t num)
{
	size_t len = strlen(parr2);
	assert(parr1 && parr2);
	if (len <= num)
	{
		char* ret = parr1;
		while (len--)
		{
		    *parr1++ = *parr2++;
		}
		*parr1 = '\0';
		return ret;
	}
	else
	{
		char* arr = parr1;
		while (num--) 
		{
			*parr1++ = *parr2++;
		}
		*parr1 = '\0';
		return arr;
	}
}

6.strstr的模拟实现(寻找字串的函数)

返回源字符串中的第一个子串的位置处

char* my_strstr(const char* parr1, const char* parr2)
{
	assert(parr1 && parr2);
	const char* cp = parr1;
	char* s1 = NULL;
	char* s2 = NULL;
	while (*cp)
	{
		const char*s1 = cp;
		const char*s2 = parr2;
		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cp;
		}
		cp++;
	}
	return NULL;
} 

7.strtok函数

char * strtok (char *str, const char * delim);

当strtok()在参数str的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回指向被分割出片段的指针,具体代码使用如下图所示:

int main()
{
	char arr[] = "aa&bbb.c12c&ddd";
	char arr1[50] = { 0 };
	strcpy(arr1, arr);
	const char* ret = "&.";
	char* str = NULL;
	for (str = strtok(arr1, ret); str != NULL; str = strtok(NULL, ret))
	{
		printf("%s\n", str);
	}
	return 0;
}
//strtok为分割字符串的函数,首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL

8.内存操作函数memcpy的模拟实现

//memcpy函数是字符串拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存
//地址的起始位置中
//memcpy与strcpy有以下不同: 
//1.可以拷贝的内容不同。strcpy只能拷贝字符串,而memcpy不限制类型,字符数组、整型、结构体、类等。 
//2.拷贝的方法不同。strcpy遇到被复制字符串的'\0'结束,memspy由第三个参数决定复制的长度,即受到长度
//限制  
void* my_memcpy(void* dest, const void* src, size_t sum)
{
	assert(dest && srckaobei);
	void* ret = dest;
	while (sum--)
	{
		*((char*)dest)++ = *((char*)src)++;
	}
	return ret;
}

9.内存操作函数memmove的模拟实现

//memmove不用考虑内存覆盖的问题,是memcpy的进化版
//即目标在前,从前往后拷贝,目标在后,从后往前拷贝
void* my_memmove(void* dest, const void* src, size_t sum)
{
	void* ret = dest;
	if (dest < src)
	{
		int i = 0;
		while (sum--)
		{
			*((char*)dest+i) = *((char*)src+i);
			i++;
		}
	}
	else
	{
		while (sum--)
		{
			*((char*)dest+sum) = *((char*)src+sum);
		}
	}
	return ret;
}

10.内存操作函数memset

memset() 函数是初始化内存的函数,通常为新申请的内存进行初始化,它是直接操作内存空间的

void *memset(void *str, int num, size_t n)

将指针变量 str 所指向的前 n 字节的内存单元用一个“整数” num 替换,num 是 int 型。str 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。memset 函数的第三个参数 n 的值一般用 sizeof() 获取。

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值