模拟实现C库函数:strchr、strcmp、strstr、memcpy和memmove

函数原型:char *strchr(const char *s, int c)  

功能: 查找字符串s中首次出现c字符的位置

说明: 返回首次出现c的位置的指针,返回的地址是被查找的字符串指针开始的第一个与c相同字符的指针,若s中不存在c则返回NULL。

返回值: 成功返回要查找的字符第一次出现的位置,否则返回NULL。

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
char *my_strchr(const char *s, char c)
{
	if (s == NULL)
	{
		return NULL;
	}

	while (*s != '\0')
	{
		if (*s == c)
		{
			return s;
		}
		s++;
	}
	return NULL;
}
int main()
{
	char str[] = "This is a sample string";
	char * pch;
	printf("Looking for the 's' character in \"%s\"...\n", str);
	pch = my_strchr(str, 's');

	//输出每个's'的位置
	while (pch != NULL)
	{
		printf("found at %d\n", pch - str + 1);
		pch = my_strchr(pch + 1, 's');
	}
	system("pause");
	return 0;
}


函数原型:int strcmp(const char *dest, const char *source) ;

返回值:返回整数值,如果dest > source,则返回值大于0,如果dest = source,则返回值等于0,如果dest < source ,则返回值小于0。字符大小是按照字符的字典序列进行排列的。

参数说明:都是以''/0''为结束符的字符串

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
int *my_strcmp(const char *str1, const char *str2)
{
	assert(str1);
	assert(str2);
	int ret = 0;
//可以根据ret的值比较大小,进入循环是为了用ret的值来比较大小
	while (!(ret = *str1 - *str2) && *str1 && str2)
	{
		str1++;
		str2++;
	}
	if ((*str1 == '\0') && (*str1 == '\0'))
	{
		return 0; //一样大
	}
	else
	{
		if (ret > 0)
		{
			ret = 1; //str1大
		}
		else
		{
			ret = -1; //str2大
		}
		return ret;
	}
}
int main()
{
	//注意,判断是否相等,是比较大小,不是比较长度
	const char *str1 = "123456";
	const char *str2 = "12345678";
	int eq = my_strcmp(str1, str2);
	printf("%d\n", eq);
	system("pause");
	return 0;
}

C语言库函数用于在字符串中查找子串。

函数原型:char *strstr(const char *s1, const char *s2)

函数的参数是两个字符串,函数返回s2在s1中第一次出现的位置。如果在s1中没有找到s2,返回空。

如果s2为空,则返回s1。 

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
char *my_strstr(const char *str, const char *subStr)
{
	assert(str);
	assert(subStr);
	assert(strlen(str) >= strlen(subStr));

	if (*subStr == '\0')
		return NULL;

	while (*str)
	{ 
		const char *start = str;
		const char *target = subStr;
		while (*target) 
		{
			if (*start && *target && (*start == *target))
			{
				start++;
				target++;
			}
			else
			{
				break;
			}
		} 
//到这里是遍历完所有subStr(或者target)所有字符,如果找到subStr(或者target)= \0
		if (*target == '\0')
		{
			return str; //找到
		}
		str++; //未找到
	}
//以上是对str一个字符的查找

	return NULL; //找完str里面所有字符,未找到
}
int main()
{

	char *s1 = my_strstr("abcdefg12345", "fg1");
	printf("%s\n", s1);

	char *s2 = my_strstr("abcdefg12345", "fg15");
	printf("%s\n", s2);

	system("pause");
	return 0;
}

函数原型:void *memcpy(void*dest, const void *src, size_t n);

功能:由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。

头文件:#include<string.h>

返回值:函数返回一个指向dest的指针。

说明:

  1.source和destination所指内存区域不能重叠,函数返回指向destin的指针。

  2.与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;

例:

  char a[100], b[50];

  memcpy(b, a,sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。

  strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:

  char a[100], b[50];

       strcpy(a,b);

  3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。

注意:source和destination都不一定是数组,任意的可读写的空间均可。

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void *my_memcpy(void *dst, const void *src, size_t count)
{
	assert(dst);
	assert(src);
	void *ret = dst;
	while (count--)
	{
		*((char*)dst) = *((char*)src); //强转成char*后再*(解引用)才能比较
		dst = (char*)dst + 1; //强转成char*后指针才能向后加1
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	char *str = "hello world!";
	char arr[64];
	my_memcpy(arr, str, strlen(str) + 1);
	printf("%s\n", arr);
	system("pause");
	return 0;
}

memmove 函数原型:extern void *memmove(void *dest, const void *src, unsigned int count);

头文件:#include <string.h>

功能:由src所指内存区域复制count个字节到dest所指内存区域。

说明:src和dest所指内存区域可以重叠,但复制后src内容会被更改。函数返回指向dest的指针。

注意:

1、它的返回值是void*,参数类型也是void*,这样它才可以处理不同类型的数据。

2、目标dest不能加const,源src加const。原因是我们需要从源src中拷贝数据到dest中,需要对dest进行赋值。若用const保护                                 dest,便不能完成赋值操作。

               memmove的好处是可以处理dest与src发生内存重叠的情况

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void *my_memmove(void *dst, const void *src, size_t count)
{
	assert(dst);
	assert(src);
	assert(count > 0);
	char *ret = (char*)dst;
	char *source = (char*)src;
	char *destination = (char*)dst;
	int i = 0;
	while (count > 0)
	{
		if (source < destination && source + count > destination)
		{
			*(destination + count - 1) = *(source + count - 1);
		}
		else
		{
			*(destination + i) = *(source + i);
			i++;
		}
		count--;
	}
}
int main()
{
	char str[64] = "hello world!";
	char arr[64];
	my_memmove(arr, str, strlen(str) + 1);
	printf("%s\n", arr);
	my_memmove(str + 3, str, strlen(str) + 1);
	printf("%s\n", str);
	system("pause");
	return 0;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值