1 strcpy

为什么strcpy要有返回值?

 返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。
    链式表达式的形式如:
        int iLength=strlen(strcpy(strA,strB));
    又如:
        char * strA=strcpy(new char[10],strB);
    返回strSrc的原始值是错误的。其一,源字符串肯定是已知的,返回它没有意义。其二,不能支持形如第二例的表达式。其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。

 

 

strcpy的原型为extern char* strcpy(char *dest,const char *src);它包含在头文件string.h中,它的返回值指向dest的指针,其功能是把src所指由NULL结束的字符串复制到dest所指的数组中。值得注意的是,src和dest所指内存区域不可以重叠,且dest必须有足够的空间来容纳src的字符串,src字符串尾的字符串结束标志'\0'也会被复制过去。

char* strcpy(char *strDes, char *strSrc)
{
    if (strDes == strSrc)                       //判断是否相等
        return strDes;
    assert(strDes != NULL && strSrc != NULL);   //判空
    char *des = strDes;                         //保存strDes基址
    while ((*des++ = *strSrc++) != '\0')       //判断结束
        ;
    return strDes;
}

字符串拷贝函数需要考虑到以下几点:

  1. 原字符串与目标字符串内存重叠
  2. 对原字符串和目标字符串进行NULL检查
  3. 保存目标字符串strDes基址
  4. 赋值过程中递增以及判空

2 strncpy

char* strncpy(char *strDes, char *strSrc, size_t n)
{
    if (strDes == strSrc)
        return strDes;
    assert(n > 0 && strDes != NULL && strSrc != NULL);
    char *des = strDes;
    while ((*des++ = *strSrc++) != '\0' && n-- > 0)
        ;
    if (*(--des) != '\0')
        *des = '\0';
    return strDes;
}

3 memcpy

注意:memcpy memmove区别和实现

memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。

但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。

memmove的处理措施:

(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝

(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝

(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝

memcpy是C语言中的内存复制函数,它的函数原型为void *memcpy(void *dest,const void *src,size_t n).它的目的是将src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内,函数返回指向dest的指针。需要注意的是,src和dest所指内存区域不能重叠,同时,与strcpy相比,memcpy遇到'\0'不结束,而是一定要复制完n个字节。而且如果目标数组dest本身已有数据,执行memcpy()之后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到要追加数据的地址。

memmove()函数用来做内存复制,可以拿他来复制任何数据类型的对象,可以指定复制的数据长度。

void *memmove(void *dest,void *src,size_t count)
{
    char *pdest=(char*)dest;
    const char *psrc=(const char*)src;
    if(pdest>psrc&&pdest<(pstr+count)) //有重叠区域
    {
        for(size_t i=count-1;i>=0;--i)
            pdest[i]=psrc[i];
    }
    else
    {
        for(size_t i=0;i<count;i++)
        {
            pdest[i]=psrc[i];
        }
    }
    return dest;
}

memcpy实现:

void* memcpy(void* dest, void* source, size_t count)

      {

           void* ret = dest;

          //copy from lower address to higher address

          while (count--)

                  *dest++ = *source++;


           return ret;

      }

 4 实现字符串转换为整型(atoi)

注意:a 空格 b 正负号 c 是否为数字 d 是否会溢出

    int atoi(string str) {
        if(str.empty())
            return 0;
        int i=0;
        while(str[i]==' ') i++;
        int flag=1;
        if(str[i]=='-')
        {
            flag=-1;
            i++;
        }
        else if(str[i]=='+')
            i++;
        long long res=0;
        while(str[i]!='\0'&&isdigit(str[i]))
        {
            res=res*10+(int)(str[i]-'0');
            if(flag==1&&res>INT_MAX)
                return INT_MAX;
            else if(flag==-1&&-res<INT_MIN)
                return INT_MIN;
            i++;
        }
        return flag*res;
    }

5 实现itoa

注意:a 正负号 b 结尾添加'\0'

char *itoa(int num)
{
    char str[1024];
    int sign=num,i=0,j=0;
    char temp[11];
    if(sign<0)
    {
        num=-num;
    }
    while(num>0)
    {
        temp[i]=num%10+'0';
        num/=10;
        i++;
    }
    if(sign<0)
    {
        temp[i++]='-';
    }
    temp[i]='\0';
    i--;
    while(i>=0)
    {
        str[j]=temp[i];
        i--;
        j++;
    }
    str[j]='\0';
    return str;
}

 6 不使用任何变量,如何实现计算字符串长度的函数strlen()

使用变量时,strlen的实现

int strlen(const char *str)
{
    int len=0;
    if(str==NULL)
        return len;
    while(*str++!='\0') len++;
    return len;
}

不使用变量,实现:

int strlen(const char *s)
{
    if(*s=='\0')
        return 0;
    else
        return 1+strlen(++s);
}

 7 strchr实现

char *strchr(const char *str,int c)
{
    assert(str!=NULL);
    while(*str!='\0'&&*str!=(char)c) ++str;
    if(*str=='\0')
        return NULL;
    return str;
}

8 strcmp实现

int strcmp(const char *s,const char *t)
{
    assert(s!=NULL&&t!=NULL);
    while(*s!='\0'&&*t!='\0'&&*s==*t)
    {
        ++s;
        ++t;
    }
    return (*s-*t);
}

9 strcat实现

char *strcat(char *strDes,const char *strSrc)
{
    assert(strDes!=NULL&&strSrc!=NULL);
    char *address=strDes;
    while(*strDes!='\0')
        ++strDes;
     while((*strDes++=*strSrc++)!='\0')
        ;
     return address;
}