C语言面试常撕的几个str代码-【strcpy】【memcpy】【strcmp】【memcpy】【strcat】

一、字符串拷贝strcpy

代码:

char * strcpy(char * des, const char * src){
    assert( (des != NULL) && (src != NULL));
    char * p = des;
    while( (*p++ = *src++) != '\0' );
    return des;
}

要注意的点:

  1. 入参里,为了防止对src的修改,应该使用const,这是一个好习惯;这里要分清 const char * 和 char * const 的区别,因为这个可能会被面试官引申出来问。const char * src里const修饰的是src所指向的内容,不可在该函数中被修改;char * const src是指src只能指向这一地址空间,不能再进行src++的操作。
  2. assert断言宏的使用,用于检测入参的合法性,算是一种异常处理,如果真,继续运行,如果假,就调用abort终止程序。
  3. *p++ = *src++  != '\0' 是将*src赋值给*p,再判断是否是遇到结束符,最后各自++。
  4. 返回 des 的目的是为了方便链式操作。

二、内存拷贝memcpy

代码:

void * memcpy(void * des, const void * src, size_t size){
    assert( (des != NULL) && (src != NULL));
    char * tmpd = (char *)des;
    char * tmps = (char *)src;
    while(size-- > 0)
        *tmpd++ = *tmps++;
    return des;
}

要注意的点:

  1. const和assert及返回值不再赘述。
  2. 要用void*型指针来接收入参,因为使用void * 可以接受任何类型的指针。
  3. 入参多一个size,用来控制复制长度。因为memcpy是内存拷贝,不是以 '\0' 为结尾标志位的。
  4. 在复制偏移之前,要先将入参转换为char *,因为入参不一定是什么类型,指针偏移都是按照类型占几个字符来自动偏移的,比如int *p = &a;现在p指向a的地址,但是p++后,p指向的地址其实是 (&a) + 4,同理如果p是char * 类型,则指向的是 (&a) + 1。所以要在复制偏移之前,将入参类型强转为char *。
  5. memcpy有一个很重要的潜在问题,就是内存重叠。解决办法是从后往前拷贝遍历,才能保证des可以得到原汁原味的src

三、字符串比较strcmp

代码

//功能:str1 > str2 返回1,反之返回-1,相等返回0
int strcmp(const char * str1, const char * str2){
    assert( (str1 != NULL) && (str2 != NULL));
    int ret = 0;
    while( *str1 != '\0' && *str2 != '\0' && *str1 == *str2 ){
        str1++;
        str2++;
    }
    if(  *str1 != '\0' && *str2 == '\0') return 1;//str1比str2长
    else if( *str1 == '\0' && *str2 != '\0') return -1;//str1比str2短
    else if( *str1 > *str2) return 1;
    else if( *str1 < *str2) return -1;
    return 0;//如果前面都没return,那就说明都一样
}

要注意的点:

  1. 入参const,assert不在赘述。
  2. 在while循环结束后,要使用if else if的结构,避免单独使用多个if,显得代码风格更优雅

四、内存比较memcmp

代码

//功能:比较内存值是否相同
int memcmp(const void *buffer1,const void *buffer2, size_t size){
    if (!size)  return 0;
    char * m1 = (char *)buffer1;
    char * m2 = (char *)buffer2;
    while ( --size && *m1 == *m2){
        m1++;
        m2++;
    }
    if(size == 0) return 0;
    else if(*m1 > *m2) return 1;
    else return -1;
}

要注意的点:

  1. https://blog.csdn.net/watergear/article/details/79531063 对于memcmp的效率问题,这篇文章探究的很清楚,大概意思是做了8字节对齐,用上了并行优化
  2. 在while循环中,如果使用size--的话,就会造成在buffer1 == buffer2 的情况下,退出循环时size = -1的情况

五、字符串拼接strcat

代码

char * strcat( char * des, const char * src){
    assert( (str1 != NULL) && (str2 != NULL));
    char * p = des;
    while(*p != '\0') p++;//找到des的结尾
    while( (*p++ = *src++) != '\0' );//开始往后复制,不用管'\0',会自动添加
    return des;
}

要注意的点:

  1. 先找到des的结尾,然后从其结尾的'\0'开始覆盖,一直到src的'\0'
  2. 最后的'\0'不用人工添加,会自动添加
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值