1、模拟实现strcpy
//src是源字符串,不可改变,故用const修饰;char*(指向char的指针)
char* MyStrcpy(char *dst, const char *src)
{
//判断指针是否为空,保证代码的健壮性
assert((NULL != dst) && (NULL != src));
//复制后,dst的地址应该是不变的,所以要保存dst的原地址
char *ret = dst;
//注意是*src指向的值不等于'\0,可省略不写
while (*(dst++) = *(src++) != '\0')
{
;
}
return ret;
}
2、模拟实现strlen
1)非递归
size_t my_strlen(const char *str)
{
int count = 0;
assert(NULL != str);
while('\0' != *str)
{
count++;
str++;
}
return count;
}
2)size_t my_strlen(const char *str)
{
char *p = str;
while(‘\0’ != *str)
{
str++;
}
return p - s;
}
3)递归
第一步:用assert宏做入口校验。(需注意!)
第二步:判断参数指针指向的值是否为零,如果是,那么表明这是一个空字符串或者是字符串的结束标志。
第三步:如果参数指针指向的值不为零,则说明指针指向的值是一个字符串。既然这个指针存放了一个字
符,那就计数为1,指针加1在调用其本身。如此循环到字符串的结束标志符‘\0’时,递归停止。
size_t my_strlen(const char *str)
{
assert(NULL != str);
if (‘\0’== *str)
return 0;
else
return (1 + my_strlen(str+1));
//assert(NULL != str);
//return (‘\0’!= *str) ? (1 + my_strlen(str+1)) : 0;
}
3、模拟实现strcat
char *my_strcpy(char *dst, const char *src)
{
char *ret = dst;
assert(NULL != dst);
assert(NULL != src);
while ('\0' != *dst)
{
dst++;
}
while (*dst++ = *src++)
{
;
}
return ret;
}
4、模拟实现strcmp
1)
int my_strcmp(const char *src, const char *dst)
{
while (*src == *dst)
{
if ('\0' == *src)
{
return 0;
}
src++;
dst++;
}
return *src - *dst;
}
2)
int my_strcmp(const char *src, const char *dst)
{
int ret = 0;
//当两个字符串的字符相等时,执行while循环,而*dst是为了确保相等的这个字符不为\0
//其中,*dst与1)中的if句功能相当
while (!(ret = *(unsigned char*)src) == *(unsigned char*)dst && *dst)
{
src++;
dst++;
}
if (ret < 0)
return -1;
else if (ret > 0)
return 1;
return ret;
}
5、模拟实现strstr
使用strstr函数可以在一个字符串中查找一个子串。它的原型如下:
char *my_strstr(char const *str1, char const *str2)
strstr函数的实现方式:这个函数在str1中查找整个str2第一次出现的起始位置,并返回一个
指向该位置的指针。如果str2没有完整的出现在str1中的任何地方,函数将返回一个NULL指针。
如果第2个参数是一个空字符串,函数就返回str1.
# include<stdio.h>
# include<stdlib.h>
# include<assert.h>
char *my_strstr(const char *str1, const char *str2)
{
char *s1 = str1;
char *s2 = str2;
char *cp = s1;
assert(str1);
assert(str2);
if ('\0' == *str2)
{
return str1;
}
while ('\0' != *cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if ('\0' == *s2)
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char *str1 = "abbbcde";
char *str2 = "0";
char *ret = my_strstr(str1, str2);
if (0 == ret)
{
printf("不存在!\n");
}
else
{
printf("%s\n", ret);
}
system("pause");
return 0;
}
运行结果:
注:
str1表字符串的原始位置,str2表子串的原始位置,cp表在字符串“查找”中的原始位置,
s1表在字符串查找中的“顺序”位置,s2表子串在查找中的“顺序”位置。每次查找完,
s2返回str2原始位置重新查找,s1返回str1查找中的位置重新查找即cp的位置。
6、模拟实现memcpy
memcpy是内存拷贝函数,拷贝的是内存块,对于长度大于一个字节的数据,要确
保把数量和数据类型的长度相乘,即count*sizeof(arr[0])。它的原型如下:
void *my_memcpy(void *dst, const void *src, size_t count)
使用memcpy函数,可以从src的起始位置复制count个字节到dst的内存起始位置,
能复制任何类型的值,
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
void *my_memcpy(void *dst, const void *src, size_t count)
{
void *ret = dst;
assert(dst);
assert(src);
while (count--)
{
*(char *)dst = *(char *)src;//void*类型指针不能直接解引用运算
dst = (char *)dst + 1;//要强制类型转换
src = (char *)src + 1;
}
return ret;
}
//void *my_memcpy(void *dst, const char *src, size_t count)
//{
// char *pdst = dst;
// char *psrc = src;
// assert(dst);
// assert(src);
// while(count--)
// {
// *pdst++ = *psrc++;
// }
// return dst;
//}
int main()
{
int arr1[50] = { 0 };
int arr2[] = { 1, 2, 3, 4, 5 };
int *ret = my_memcpy(arr1, arr2, 4);
int i = 0;
for (i = 0; i < (sizeof(arr2)/4); i++)
{
printf("% d", ret[i]);
}
printf("\n");
system("pause");
return 0;
}
运行结果为:
7、模拟实现memmove
memmove函数的行为和memcpy差不多,只是它的源和目标操作数可以重叠。
使用memove函数把源操作数复制到一个临时位置,这个临时位置不会与源或
目标操作数重叠,然后再把它再把从临时位置复制到目标操作数。
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
void *my_memmove(void *dst, const void *src, size_t count)
{
void *ret = dst;
assert(dst);
assert(src);
//从前往后
if (dst <= src)
{
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
//从后往前
else
{
while (count--)
{
*((char *)dst + count) = *((char *)src + count);
}
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = { 5, 4, 3, 2, 1 };
int i = 0;
int ret = my_memmove(arr1 + 2, arr1 + 3, 20);
for (i = 0; i < (sizeof(arr1) / 4); i++)
{
printf("% d", arr1[i]);
}
printf("\n");
system("pause");
return 0;
}
运行结果:
注:要先判断src和dst的位置关系,如果dst在src的前面,那么从前往后
复制;如果dst在src的后面,那么从后往前复制。1、模拟实现strcpy
//src是源字符串,不可改变,故用const修饰;char*(指向char的指针)
char* MyStrcpy(char *dst, const char *src)
{
//判断指针是否为空,保证代码的健壮性
assert((NULL != dst) && (NULL != src));
//复制后,dst的地址应该是不变的,所以要保存dst的原地址
char *ret = dst;
//注意是*src指向的值不等于'\0,可省略不写
while (*(dst++) = *(src++) != '\0')
{
;
}
return ret;
}
2、模拟实现strlen
1)非递归
size_t my_strlen(const char *str)
{
int count = 0;
assert(NULL != str);
while('\0' != *str)
{
count++;
str++;
}
return count;
}
2)size_t my_strlen(const char *str)
{
char *p = str;
while(‘\0’ != *str)
{
str++;
}
return p - s;
}
3)递归
第一步:用assert宏做入口校验。(需注意!)
第二步:判断参数指针指向的值是否为零,如果是,那么表明这是一个空字
符串或者是字符串的结束标志。
第三步:如果参数指针指向的值不为零,则说明指针指向的值是一个字符串。
既然这个指针存放了一个字符,那就计数为1,指针加1在调用其本身。如此
循环到字符串的结束标志符‘\0’时,递归停止。
size_t my_strlen(const char *str)
{
assert(NULL != str);
if (‘\0’== *str)
return 0;
else
return (1 + my_strlen(str+1));
//assert(NULL != str);
//return (‘\0’!= *str) ? (1 + my_strlen(str+1)) : 0;
}
3、模拟实现strcat
char *my_strcpy(char *dst, const char *src)
{
char *ret = dst;
assert(NULL != dst);
assert(NULL != src);
while ('\0' != *dst)
{
dst++;
}
while (*dst++ = *src++)
{
;
}
return ret;
}
4、模拟实现strcmp
1)
int my_strcmp(const char *src,const char *dst)
{
while (*src == *dst)
{
if ('\0' == *src)
{
return 0;
}
src++;
dst++;
}
return *src - *dst;
}
2)
int my_strcmp(const char *src,const char *dst)
{
int ret = 0;
//当两个字符串的字符相等时,执行while循环,而*dst是为了确保相等的这个字符不为\0
//其中,*dst与1)中的if句功能相当
while (!(ret = *(unsigned char*)src) == *(unsigned char*)dst && *dst)
{
src++;
dst++;
}
if (ret < 0)
return -1;
else if (ret > 0)
return 1;
return ret;
}
5、模拟实现strstr
使用strstr函数可以在一个字符串中查找一个子串。它的原型如下:
char *my_strstr(char const *str1, char const *str2)
strstr函数的实现方式:这个函数在str1中查找整个str2第一次出现的起始位置,
并返回一个指向该位置的指针。如果str2没有完整的出现在str1中的任何地方,
函数将返回一个NULL指针。如果第2个参数是一个空字符串,函数就返回str1.
# include<stdio.h>
# include<stdlib.h>
# include<assert.h>
char *my_strstr(const char *str1,const char *str2)
{
char *s1 =str1;
char *s2 =str2;
char *cp = s1;
assert(str1);
assert(str2);
if ('\0' == *str2)
{
return str1;
}
while ('\0' != *cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if ('\0' == *s2)
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char *str1 ="abbbcde";
char *str2 ="0";
char *ret = my_strstr(str1, str2);
if (0 == ret)
{
printf("不存在!\n");
}
else
{
printf("%s\n", ret);
}
system("pause");
return 0;
}
运行结果:
注:
str1表字符串的原始位置,str2表子串的原始位置,cp表在字符串“查找”中的原始位置,
s1表在字符串查找中的“顺序”位置,s2表子串在查找中的“顺序”位置。每次查找完,s2
返回str2原始位置重新查找,s1返回str1查找中的位置重新查找即cp的位置。
6、模拟实现memcpy
memcpy是内存拷贝函数,拷贝的是内存块,对于长度大于一个字节的数据,要确保
把数量和数据类型的长度相乘,即count*sizeof(arr[0])。它的原型如下:
void *my_memcpy(void *dst,const void *src,size_t count)
使用memcpy函数,可以从src的起始位置复制count个字节到dst的内存起始位置,能复制任何类型的值,
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
void *my_memcpy(void *dst,const void *src,size_t count)
{
void *ret =dst;
assert(dst);
assert(src);
while (count--)
{
*(char *)dst = *(char *)src;//void*类型指针不能直接解引用运算
dst = (char *)dst + 1;//要强制类型转换
src = (char *)src + 1;
}
return ret;
}
//void *my_memcpy(void *dst, const char *src, size_t count)
//{
//char *pdst = dst;
//char *psrc = src;
//assert(dst);
//assert(src);
//while(count--)
//{
//*pdst++ = *psrc++;
//}
//return dst;
//}
int main()
{
int arr1[50] = { 0 };
int arr2[] = { 1, 2, 3, 4, 5 };
int *ret = my_memcpy(arr1, arr2, 4);
int i = 0;
for (i = 0; i < (sizeof(arr2)/4); i++)
{
printf("% d", ret[i]);
}
printf("\n");
system("pause");
return 0;
}
运行结果为:
7、模拟实现memmove
memmove函数的行为和memcpy差不多,只是它的源和目标操作数可以重叠。
使用memove函数把源操作数复制到一个临时位置,这个临时位置不会与源或
目标操作数重叠,然后再把它再把从临时位置复制到目标操作数。
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
void *my_memmove(void *dst,const void *src,size_t count)
{
void *ret =dst;
assert(dst);
assert(src);
//从前往后
if (dst <=src)
{
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
//从后往前
else
{
while (count--)
{
*((char *)dst +count) = *((char *)src +count);
}
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = { 5, 4, 3, 2, 1 };
int i = 0;
int ret = my_memmove(arr1 + 2, arr1 + 3, 20);
for (i = 0; i < (sizeof(arr1) / 4); i++)
{
printf("% d", arr1[i]);
}
printf("\n");
system("pause");
return 0;
}
运行结果:
注:要先判断src和dst的位置关系,如果dst在src的前面,那么从前往后复制;
如果dst在src的后面,那么从后往前复制。