有关不调用库函数的字符串操作!

有关不调用库函数的字符串操作!

 

char *strstr(char *str1,char *str2);在字符串str1中,寻找字串str2,若找到返回找到的位置,否则返回NULL。

#include <iostream>
char *strstr(char *str1,char *str2)
{
  char *s1,*s2;
  assert(( str1 != (char *)0 && (str2 != (char *)0));
  
  /* 空字符串是任何字符串的子字符串 */
  if('/0' == *str2)
  {
   return ((char *)str1);
  }

  while(*str1)
  {
    s1 = (char *)str1;
    s2 = (char *)str2;
    
    while((*s1 == *s2) && *s1 && *s2)
    {
     s1++;
     s2++;
    }
    
    if('/0' == *s2)
    {
      return ((char *)str1);
    }
    str1++;
  }
  
  /* 查找不成功,返回NULL */ 
  return((char *)0);
}

void *memcpy(void *pvTo, const void *pvFrom, size_t size)
{
        assert((pvTo != NULL) && (pvFrom != NULL));     // 使用断言
        byte *pbTo = (byte *) pvTo;     // 防止改变pvTo的地址
        byte *pbFrom = (byte *) pvFrom; // 防止改变pvFrom的地址
        while(size -- > 0 )
            *pbTo ++ = *pbFrom ++ ;
        return pvTo;
}

第二种:转自变态之MEMCPY
void* mymemcpy( void* dest, const void* src, size_t count )
{
    char* d = (char*)dest;
    const char* s = (const char*)src;
    int n = (count + 7) / 8; // count > 0 assumed  没有检查count为0的情况

    switch( count & 7 )
    {
    case 0: do { *d++ = *s++;
    case 7:        *d++ = *s++;
    case 6:        *d++ = *s++;
    case 5:        *d++ = *s++;
    case 4:        *d++ = *s++;
    case 3:        *d++ = *s++;
    case 2:        *d++ = *s++;
    case 1:        *d++ = *s++;
               } while (--n > 0);
    }

    return dest;
}
解释:
int n = (count + 7) / 8;计算要复制的轮数(每轮复制8位),剩下的余数位数也要复制进去。
count & 7控制要复制余数位数,while (--n > 0)控制轮数。
比如count = 9,则n = 2,count & 7 = 1,要复制2轮,程序跳到case1执行,复制一位之后,再循环一轮,复制8位.

为何这么实现:引用上面帖子后面的评论:

每8个字节拷贝省7个跳转(AMD处理器内部分支预测算法是“假定全都跳转”,因此这里也就是相当于省了7个时钟周期);把swith和do循环凑到一起,多少省几个字节的空间…… 
但使用32位或64位指令,可以得到更大的优化效果,代码还要精炼得多。 
说实在话:除非内存小到极点、并且无法增加的系统,写出这样的程序纯属作孽……

后记:一般出题目让你实现memcpy,个人理解,其意图至少有以下几点:

1.写任何程序都能反映出你的代码风格.

2.考查你是否注意到,要拷贝的源,即const void* src,应该是用const的,避免有意或无意的修改.

3.指针的类型转化问题,原始参数应该是void *的,你具体操作的时候,应该是转化为某种具体的类型,此处用char比较适合.

4.注意要判断源src是否和dest重复,如果重复,直接返回或返回错误.

5.应该还有其他考虑,如果以后想到,再补充.

//字符串拷贝:
char *strcpy(char *strDest, const char *strSrc)
{
    assert((strDest!=NULL) && (strSrc !=NULL));   // 使用断言

    char *address = strDest;                   

    while( (*strDest++ = * strSrc++) != ‘/0’ )   
      return NULL ;

    return address ;
}

 

 

//strrpl库函数:

/* 把 s 中的字符串 s1 替换成 s2 */
char *strrpl(char *s, const char *s1, const char *s2)
{
        char *ptr;
        while (ptr = strstr(s, s1))     /* 如果在s中找到s1 */
        {
           memmove(ptr + strlen(s2) , ptr + strlen(s1), strlen(ptr) - strlen(s1) + 1);
           memcpy(ptr, &s2[0], strlen(s2));
        }
        return s;
}

//内存拷贝:
#include <iostream>
using namespace std;
void* memcpy(void* dest,const void *src,size_t count)
{
 char* pdest=static_cast<char*>(dest);
 const char* psrc = static_cast<const char*>(src);
 if(pdest>psrc && pdest<psrc+count)
 {
  for(size_t i=count-1; i!=-1;i--)
  pdest[i]=psrc[i];
 }
 else
 {
  for(size_t i=0;i<count;i++)
  pdest[i]=psrc[i];
 }
 return dest;
}

 

 

//查找字符在字符串中出现的次数:
 int count1(char* str,char* s)
{
    char* s1;
    char* s2;
    int count = 0;
    while(*str!='/0')
    {
        s1 = str;
        s2 = s;
        while(*s2 == *s1&&(*s2!='/0')&&(*s1!='0'))
        {
            s2++;
            s1++;
        }
        if(*s2 == '/0')
            count++;
        str++;
    }
    return count;
}

转载于:https://my.oschina.net/lCQ3FC3/blog/753267

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值