模拟实现库函数

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的后面,那么从后往前复制。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值