C语言自定义实现对string库函数的功能

1:strcpy函数将源字符串拷贝到目标字符串,目标字符串的长度必须要大于源字符串长度:注释部分为原始版本,代码较为冗长

char *MyStrcpy(char *str1, const char *str2){
	/*if (strlen(str2) > strlen(str1)){
		printf("Error");
		return;
	}
	char *p = str1;
	while (*(str2) != '\0'){
		*(str1) = *(str2);
		str1++;
		str2++;
	}
	*str1 = '\0';*/
	char *p = str1;
	while (*str1++ = *str2++){

	}
	return p;
}

2:strcat函数将源字符串拼接到目标字符串后,目标字符串的长度要足够长容纳两个字符串。

char *MyStrcat(char *str1, const char *str2){
    /*int len1 = strlen(str1);
    int len2 = strlen(str2);
    if (ROW < len1 + len2){
        printf("Error");
        return;
    }

    while (*(str2) != '\0'){
        *(str1 + len1) = *str2;
        str1++;
        str2++;
    }*/
    char *p = str1;
    while (*str1 != '\0'){
        str1++;
    }
    while (*str1++ = *str2++){

    }
    return p;
}

3:strncat函数将源字符串的指定长度拼接到目标字符串后面,目标字符串的长度要足够长容纳两个字符串。

char *MyStrncat(char *str1, const char *str2, int n){
	char *p = str1;
	while (*str1 != '\0'){
		str1++;
	}
	while (n!=0){
		*str1++ = *str2++;
		n--;
	}
	return p;
}

4:strstr函数在目标字符串中寻找源字符串,若目标字符串中存在则返回目标字符中源字符串第一个字符的地址,否则返回NULL。

const char *MyStrstr(const char *str1, const char *str2){
	//int len1 = strlen(str1);
	//int len2 = strlen(str2);
	//char *left = str1;
	//char *right = str1+len2-1;
	//while (left <= right && right<(str1+len1)){//循环终止条件当left大于right或者right所指地址大于str1的长度
	//	char *result = left;//标记第一个字母做返回地址
	//	while (*(left) == *(str2) && *(right) == *(str2+len2-1)){//判断str1中left和str2第一个字母right和str2最后一个字母是否相同
	//		while (left <= right){//继续判断里面的内容
	//			left++;
	//			right--;
	//			if (left == right){//当left和right所指地址相同时即完全相同
	//				return result;//返回标记地址
	//			}
	//		}
	//		left = result;//当中间元素不同时退回第一次所指元素地址
	//		right = result + len2 - 1;
	//	}
	//	left++;//进行下一个元素得判断
	//	right++;
	//}
	//return NULL;//未找到相同字符段时返回空地址。
	const char *s1 = str1;
	const char *s2 = str2;
	const char *start = str1;
	while (*start != '\0'){
		s1 = start;
		s2 = str2;
		while (*s1!='\0'&&*s2!='\0'&&*s1 == *s2){
			s1++;
			s2++;
		}
		if (*s1 == '\0'){
			return NULL;
		}
		if (*s2 == '\0'){
			return start;
		}
		start++;
	}
	return NULL;
}

5:strchr函数在目标字符串中查找是否存在字符C,若存在则返回目标字符串第一次出现字符c的地址,否则返回NULL。

const char *MyStrchr(const char *str1, char c){
	assert(str1 != NULL);
	while (*(str1) != '\0'){
		if (*(str1) == c){
			return str1;
		}
		str1++;
	}
	return NULL;
}

6:strcmp:比较两个字符串的大小,若第一个字符串大于第二个字符串返回正数,小于返回负数,等于返回0;

int MyStrcmp(const char *str1, const char *str2){
  while (*(str1) != '\0' && *(str2) != '\0'){
			if (*(str1)>*(str2)){
				return 1;
			}
			if (*(str1) < *(str2)){
				return -1;
			}
			if (*(str1) == *(str2)){
				str1++;
				str2++;
			}
		}
	return 0;
}

7:strncmp函数比较两个字符串前n个字符,若第一个字符串的前n个字符于第二个字符串的前n个字符返回正数,小于返回负数,等于返回0;

int MyStrncmp(const char *str1, const char *str2, int n){
	while (n){
		while (*(str1) != '\0' && *(str2) != '\0'){
			if (*(str1)>*(str2)){
				return 1;
			}
			if (*(str1) < *(str2)){
				return -1;
			}
			if (*(str1) == *(str2)){
				str1++;
				str2++;
			}
		}
		n--;
	}
	return 0;
}

8:memcpy函数:将源数组内容拷贝n个字节数到目标数组中,数组的类型不定。且存在内存重叠问题是无法完成拷贝。

void *MyMemcpy(void *str1, const void *str2, int n){
	void *p = str1;
	while (n){
		*((char *)str1) = *((char *)str2);
		((char *)str1)++;
		((char *)str2)++;
		n--;
	}
	return p;
}

9:memove:将源数组内容拷贝n个字节数到目标数组中,数组的类型不定。解决memcpy函数存在的内存重叠问题。

void *MyMemove(void *str1, const void *str2, int n){
    void *p = str1;
    if (str2 > str1){//当拷贝到的目的地址小于源地址时从头开始拷贝,指针依次右移,向后移动。
        while (n){
            *((char *)str1) = *((char *)str2);
            ((char *)str1)++;
            ((char *)str2)++;
            n--;
        }
    }
    else{//当拷贝到的目的地址大于源地址时从需要拷贝的字节数的最后一位向前开始拷贝,指针依次左移,向前移动
        while (n--){
            *((char *)str1+n) = *((char *)str2+n);
            n--;
        }
    }
    return p;
}

内存重叠问题:

str:

1 2 3 4 5 6

str+2:

1 2 3 4 5 6

str+2指向3,当str+2作为目标地址,str作为源地址,把str拷贝16个字节到str+2中,理想拷贝结果为:1 2 1 2 3 4但按照memcpy函数执行时结果为:1 2 1 2 1 2.即存在内存重叠问题。

猜你喜欢

转载自blog.csdn.net/qq_44370562/article/details/90202989
今日推荐