字符串函数汇总

简介: 1 strcpy 为什么strcpy要有返回值?  返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。    链式表达式的形式如:        int iLength=strlen(strcpy(strA,strB));    又如:        char * strA=strcpy(new char[10],strB);    返回strSrc的原始值是错误的。

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;
}

更多参考:http://blog.csdn.net/v_JULY_v/article/details/6417600

 

相关文章
|
Linux 编译器 C语言
Linux五大步安装Python
Linux五大步安装Python
1424 0
Linux五大步安装Python
|
Linux 异构计算 Windows
Windows操作系统:指定网卡ping连通性
某些时候,板卡上留有两个及以上万兆网口,在没有其他FPGA板卡或者只是想测一下网口或者万兆光模块的通路时,可以通过回环互ping来验证下连通性
4069 0
|
移动开发 前端开发 JavaScript
淘宝小部件 Canvas 渲染流程与原理全解析
淘宝小部件 Canvas 渲染流程与原理全解析
644 0
淘宝小部件 Canvas 渲染流程与原理全解析
|
搜索推荐 大数据 测试技术
|
Oracle 关系型数据库 数据库
innodb_lock_wait_timeout参数的了解
前言:在管理ORACLE的工作中,经常发现因为锁等待的原因导致应用宕机了。Mysql考虑到自身的性能和架构等因素,InnoDB数据库引擎增加了参数innodb_lock_wait_timeout,避免在资源有限的情况下产生太多的锁等待; 一、innodb_...
3279 0
|
前端开发 JavaScript Java
基于springboot的在线心理测评系统
本系统采用springboot框架,数据层采用mybatis,数据库使用mysql,功能包含前台和后台,比如心理文章查看、留言、测评、公告等,后台维护所有信息,具体功能实现可以建议看下方的演示视频,系统适合于基础一般的同学使用。
基于springboot的在线心理测评系统
|
XML Java 数据库连接
使用 MyBatis 的 Maven 插件生成代码
使用 MyBatis 的 Maven 插件生成代码
 使用 MyBatis 的 Maven 插件生成代码
田口实验法
数有 5 个:种群大小(P_size)、进化代数(G)、精英种群占比,优先级学习参 数,工厂学习参数。本节采用 5 个影响因子等级,不同参数值得组合情况如 表 5-1 所示。选择正交数组 L25(55)。对于每种参数组合情况,算法独立运行 30 次,并取 30 次运行所获得的平均完工时间作为实验指标。
田口实验法
|
Web App开发 网络协议 算法
NAT 穿透
之前在WebRTC简介中,我们简单地讲了WebRTC中是如何进行NAT穿透的,但是我觉得当时讲的还不够详细,所以打算通过此文更加深入的总结NAT穿透技术,其中涉及到NAT,STUN协议,TURN协议,ICE协议。
|
存储 NoSQL Redis
Redis集群:主从节点添加和删除
Redis集群:主从节点添加和删除
Redis集群:主从节点添加和删除