字符串函数的实现, memmove() 函数的实现和解析

  • strlen 函数的实现
int my_strlen(char* dst) {
	assert(dst);
	char* ret = dst;
	int count = 0;
	while (*ret!='\0') {
		++ret;
		++count;
	}
	return count;
}
  • strcat 函数的实现
har* my_strcat(char* dst, const char* src) {
	assert(dst && src);
	char* ret = dst;           // 因为后边 dst需要++,所以用ret保存原来的位置
	while (*dst != '\0') {    //先找到 dst 上'\0' 的位置
		++dst;
	}
	while (*dst++ = *src++);  //当 dst 到 '\0'了,再将 src 传给 dst
	return ret;
}

和strcpy 不同的是 strcpy是拷贝,strcat是追加拷贝。

  • strcmp 函数的实现
int my_strcmp(const char* str1,const char* str2) {
	assert(str1 && str2);
	unsigned char* s1 = (unsigned char*)str1;
	unsigned char* s2 = (unsigned char*)str2;
	while (*s1 && *s2) {
		if (*s1 > *s2) {
			return 1;
		}
		else if (*s1 < *s2) {
			return -1;
		}
		else {
			++s1;
			++s2;
		}
	}
	if (*s1 == '\0'&&*s2 == '\0') {
		return 0;
	}
	else if (*s1 == '\0') {
		return -1;
	}
	else {
		return 1;
	}
}

strcmp 函数居然是根据字符串中字符的 ASCII 码大小来比较字符串大小的,我有一点不解,假如有两个字符串 str1 = “abbb” 和 str1 = “baaa”,用 strcmp 函数的话,结果是 str2 大于 str1,仅仅是因为 str2 的第一个字符 b 的 ASCII 码大于 str1 的 a。我的想法是应该比较总的 ASCII 码的大小。(仅仅是我自己的臆想,还是按照人家的来吧!)

  • strstr 函数的实现
    判断一个字符串是不是另一个字符串的子串,如果是,则该函数返回 str2 在 str1 中首次出现的地址,否则,返回NULL。
char* my_strstr(const char* src, const char* sub) {
	assert(src && sub);
	const char* srci = src;
	const char* subi = sub;
	while (*srci != '\0') {
		while (*srci == *subi && *subi != '\0') {
			++srci;
			++subi;

		}
		if (*subi == '\0') {
			return src;
		}
		else {
			subi = sub;
			++src;
			srci = src;
		}
	}
}
  • memcpy 函数的实现
void* my_memcpy(void* dst, const void* src, size_t num) {
	assert(dst && src);       
	char* str_dst = (char*)dst;
	char* str_src = (char*)src;
	for (size_t i = 0; i < num; ++i) {
		str_dst[i] = str_src[i];   // 等价于 *(str_src + i)
	}
	return dst;
}

memcpy函数和strcpy函数的一个区别在于,memcpy可以拷贝任意类型的数据,而strcpy函数只能拷贝字符串

  • memmove 函数的实现

    memmove 函数有两种实现的方法。
    在这里插入图片描述
    如图要将红色部分的数据拷贝到黑色部分,第一种情况是内存的前重叠,和不重叠,直接从 src 的前往 src 的后拷贝给 dst,不会影响结果。但是如果是内存的后重叠,如下图:
    在这里插入图片描述
    如果还是按照从前往后进行拷贝,把 src 的第一个数据拷给 dst 的第一个数据时,就已经改变了 src 后边的数据,因为 dst 第一个数据所在位置刚好重叠与 src 后边的数据,这样拷贝,已经改变了还没有拷贝给 dst 的数据,后边拷贝的数据并不是我们最初想要的。所以这种内存后重叠,我们就要从后往前进行拷贝,也就是说,先把 src 的最后一个数据拷贝给 dst 的最后一个数据,然后把 src 的倒数第二个数据拷贝给 dst 的倒数第二个数据,以此类推。这样做就不会改变还没有拷贝给 dst 的 src 数据。
    以下有两种拷贝方式,第一种是:给前重叠或者不重叠从前往后拷贝,给后重叠或者不重叠从后往前拷贝(从前往后或者从后往前拷贝都不会影响到内存不重叠的拷贝)。 第二种是:给内存前重叠或者不重叠的从前往后拷贝,给内存后重叠的从后往前拷贝。

    第一种

void* my_memmove(void* dst, const void* src, size_t num) {
	assert(src && dst);
	char* str_dst = (char*)dst;
	char* str_src = (char*)src;
	if (str_dst < str_src) { //前重叠或者不重叠,从前往后拷贝
		for (size_t i = 0; i < num; ++i) {
			str_dst[i] = str_src[i];
		}
	}
	else {//后重叠或者是不重叠,从后往前拷贝
		for (int i = num-1 ; i >= 0; --i) {
			str_dst[i] = str_src[i];
		}
	}
	return dst;
 }
**第二种**
void* my_memmove(void* dst, const void* src, size_t num) {
	assert(src && dst);
	char* str_dst = (char*)dst;
	char* str_src = (char*)src;
	if (str_src < str_dst && str_dst<str_src +num) {   //后重叠 从后往前拷贝
		for (int i = num - 1; i >= 0; --i) {
			str_dst[i] = str_src[i];
		}
	}
	else {   //前重叠或者不重叠,从前往后拷贝
		for (size_t i = 0; i < num; ++i) {
			str_dst[i] = str_src[i];
		}
	}
	return dst;
}

值得一提的是,字符串数组可以用这种方式初始化(char str[] = “abcdefg”),但是不可以用这种方式赋值,这里就可以用到字符串函数 strcpy memcpy memmove

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值