库函数的模拟实现-C语言

求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数
strncpy
strncat
strncmp
字符串查找
strstr
strtok
错误信息报告
strerror
内存操作函数
memcpy
memmove
memset
memcmp
 
1 strlen
字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
含 '\0' )。参数指向的字符串必须要以 '\0'结束。 注意函数的返回值为size_t,是无符号的
模拟实现:
size_t my_strlen(const char* str)
{
	assert(str);
	size_t count = 0;
	while (*str != '\0')
	{
		str++;
		count++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdefg";
	size_t len = my_strlen(arr);
	printf("%u", len);
	return 0;
}
2 strcpy
源字符串必须以 '\0' 结束。会将源字符串中的 '\0' 拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。目标空间必须可变。
模拟实现:
//char* my_strcpy(const char* str1, char* str2)
//{
//	char* ret = str2;
//	assert(str1 && str2);
//	while (*str1 != '\0')
//	{
//		*str2++ = *str1++;
//
//	}
//	str2 = str1;
//	return ret;
//
//}
//int main()
//{
//	char arr1[] = "abcdefgh";
//	char arr2[10] = "";
//	my_strcpy(arr1, arr2);
//	printf("%s",arr2);
//	return 0;
//}
3 strcat(字符串追加)
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
模拟实现:
char* my_strcat(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1 != '\0')
	{
		str1++;
	}
	while (*str1++ = *str2++);
	return ret;
}

int main()
{
	char arr1[10] = "hello";
	char arr2[] = "word";
	my_strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}
4 strcmp
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
模拟实现:
int my_strcmp(char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}
int main()
{
	char arr1[] = "zhangsan";
	char arr2[] = "zhangsanfeng";
	int ret = my_strcmp(arr1, arr2);
	if (ret < 0)
	{
		printf("<\n");
	}
	else if (ret == 0)
	{
		printf("==/n");
	}
	else
	{
		printf(">\n");
	}
	return 0;
}
5 strncpy
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
char* my_strncpy(char* destination, const char* source, size_t n)
{
	char* cp = destination;
	int i = 0;
	while (*source && i < n)
	{
		*cp++ = *source++;
		i++;
	}
	for (int j = i; j < n; j++)
	{
		*cp++ = 0;
	}
	return destination;
}
int main()
{
	char a[20] = "abcdefghi";
	char b[] = "xyz";
	my_strncpy(a, b, 6);
	printf("%s\n", a);
	return 0;
}

 

6 strncat
将源文件的前num字符添加到目的地,再加上一个结束的空字符。
如果源字符串的长度小于num,则只复制到结束的空字符的内容。
char* my_strncat(char* dest, const char* scr, int n)
{
	char* p = dest;
	assert(dest && scr);
	while (*p)
	{
		p++;
	}
	while (n--)
	{
		*p++ = *scr++;
	}
	*p = '\0';
	return dest;
}

int main()
{
	char arr[32] = "hello ";
	const char arr1[] = "word!";
	char* str = my_strncat(arr, arr1, 20);
	printf("%s\n", str);
	return 0;
}

 

7 strncmp
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
3fee3e5ea4c5459a8b0fc003d49cf8a9.png

 8 strstr

返回str1中第一次出现的str2的指针,如果str2不是str1的一部分,则返回一个空指针。

模拟实现:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* p = str1;
	const char* s2 = str2;
	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[] = "abbbcde";
	char arr2[] = "bcd";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}
9 strtok
sep参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标
记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
int main()
//{
//	const char* sep = "@.";
//	char email[] = "csdnboke@csdnboke.com.net";
//	char cp[40] = { 0 };
//	strcpy(cp, email);
//
//	char* ret = NULL;
//	for (ret = strtok(cp, sep); 
//		 ret != NULL; 
//		 ret=strtok(NULL, sep))
//	{
//		printf("%s\n", ret);
//	}
//	return 0;
//}
10  memcpy(其实在VS中,memcpy遇到重叠的时候也实现了memmove的功能,连函数现在都卷起来了!!!)
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
模拟实现:
void* my_memcpy(void* dest, const void* src, size_t sum)
{
	assert(dest && src);
	void* ret = dest;
	while (sum--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[] = { 0,1,2,3,4,5,6,7,8,9 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 16);
	return 0;
}
11  memmove
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
模拟实现:
void* my_memmove(void* dst, const void* src, size_t count) {
	void* ret = dst;
	if (dst <= src || (char*)dst >= ((char*)src + count)) {
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else {
		dst = (char*)dst + count - 1;
		src = (char*)src + count - 1;
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1;
			src = (char*)src - 1;
		}
	}
	return(ret);
}
int main()
{
	int arr1[] = { 0,1,2,3,4,5,6,7,8,9 };
	my_memmove(arr1 + 2, arr1, 16);
	return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

crazy_xieyi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值