C/C++面试:⼿写字符串函数 strcat,strcpy,strncpy,memset,memcpy实 现

1059 篇文章 285 订阅
#include <assert.h>
#include <cstring>

// 把 src 所指向的字符串复制到 dest,注意:dest定义的空间应该⽐src⼤
char* strcpy(char *dest,const char *src) {
    assert(dest!=NULL);//优化点1:检查输⼊参数
    assert(src!=NULL);
    
    
    char *ret = dest;
    while(*src!='\0')
        *(dest++)=*(src++);
    *dest='\0';//优化点2:⼿动地将最后的'\0'补上
    return ret;
}

// 考虑内存᯿叠的字符串拷⻉函数
char *strcpy(char *dest, char *src){
    assert(dest!=NULL);
    assert(src!=NULL);
    
    char *ret = dest;
    memmove(dest,src,strlen(src)+1);
    return ret;
}


//把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
char* strcat(char *dest,const char *src) {
    //1. 将⽬的字符串的起始位置先保存,最后要返回它的头指针
    //2. 先找到dest的结束位置,再把src拷⻉到dest中,记得在最后要加上'\0'
    assert(dest!=NULL);
    assert(src!=NULL);

    char *ret = dest;
    while (*dest != '\0'){
        dest++;
    }
    while (*src != '\0'){
        *(dest++) = *(src++);
    }
    *dest = '\0';
    return ret;
}

//把 str1 所指向的字符串和 str2 所指向的字符串进⾏⽐较。
//该函数返回值如下:
//如果返回值 < 0,则表示 str1 ⼩于 str2。
//如果返回值 > 0,则表示 str1 ⼤于 str2。
//如果返回值 = 0,则表示 str1 等于 str2。
int strcmp(const char *s1, const char *s2){
    assert(s1 != NULL);
    assert(s2 != NULL);
    while (*s1 != '\0' && *s2 != '\0'){
        if(*s1 > *s2){
            return 1;
        }else if(*s1 < *s2){
            return -1;
        }else{
            s1++; s2++;
        }
    }

    //当有⼀个字符串已经⾛到结尾
    if(*s1 > *s2){
        return 1;
    }else if(*s1 < *s2){
        return -1;
    }else{
        return 0;
    }
}


//在字符串 str1 中查找第⼀次出现字符串 str2 的位置,不包含终⽌符 '\0'
char *strstr(char *str1, char *str2){
    assert(str1 != NULL);
    assert(str2 != NULL);
    if(*str2=='\0'){
        return NULL;//若str2为空,则直接返回空
    }

    char *s = str1;
    while (*s != '\0') { //若不为空,则进⾏查询
        char *s1 = s;
        char *s2 =str2;
        while(*s1!='\0'&&*s2!='\0' && *s1==*s2)
            s1++,s2++;
        if(*s2=='\0')
            return str2;//若s2先结束
        if(*s2!='\0' && *s1=='\0')
            return NULL;//若s1先结束⽽s2还没结束,则返回空
        s++;
    }
    return NULL;
}

//模拟实现memcpy函数 从存储区 str2 复制 n 个字符到存储区 dst。
void *memcpy(void *dest, void *src, size_t num){
    assert(dest != NULL && src != NULL);
    void *ret = dest;
    for (int i = 0; i < num; ++i) {
        //因为void* 不能直接解引⽤,所以需要强转成char*再解引⽤
        *(char *)dest = *(char *)src;
        dest = (char *)dest + 1;
        src = (char *)src + 1;
    }
    return ret;
}

//考虑内存᯿叠的memcpy函数 优化的点
void *memmove(void *dest, void *src, size_t num){
    char *p1 = (char *)dest;
    char *p2 = (char *)src;
    if(p1 < p2){ //p1低地址p2⾼地址
        for (int i = 0; i < num ; ++i) {
            *(p1++) = *(p2++);
        }
    }else{//从后往前赋值
        p1+=num-1;
        p2+=num-1;
        for(size_t i=0; i!=num; ++i)
            *(p1--) = *(p2--);
    }
    return dest;
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值