memstr、strcpy、memcpy的C语言实现

1、memstr的实现

实现代码:

/**
 * @brief  在字符串full_data中查找字符串substr第一次出现的位置
 *
 * @param full_data 	源字符串首地址
 * @param full_data_len 源字符串长度
 * @param substr        匹配字符串首地址
 *
 * @returns   
 *      成功: 匹配字符串首地址
 *      失败:NULL
 */
 
 char* memstr(char* full_data, int full_data_len, char* substr) { 
	//异常处理
    if (full_data == NULL || full_data_len <= 0 || substr == NULL) { 
        return NULL; 
    } 

    if (*substr == '\0'){ 
        return NULL; 
    } 

	//匹配子串的长度
    int sublen = strlen(substr); 

    int i; 
    char* cur = full_data; 
    int last_possible = full_data_len - sublen + 1; //减去匹配子串后的长度
    for (i = 0; i < last_possible; i++) { 
        if (*cur == *substr) { 
            if (memcmp(cur, substr, sublen) == 0) { 
                //found  
                return cur; 
            } 
        }
		
        cur++; 
    } 

    return NULL; 
} 

2、memcpy的实现

  这里需要注意的就是内存覆盖,如图中1的情况。
在这里插入图片描述
实现代码:

/**
 * @brief  从src内存地址拷贝n个字节到dst内存地址中
 *
 * @param dst 	目标地址
 * @param src   源地址
 * @param n     字节长度 
 *
 * @returns   
 *      成功: 目的地址dst
 *      失败:NULL
 */
 //单字节搬运版本:(
void* my_memcpy_byte(void *dst, const void *src, int n){
	//异常情况
    if (dst == NULL || src == NULL || n <= 0) return NULL;
  
    char * p_dst = (char *)dst;
    char * p_src = (char *)src;
      
    //考虑内存覆盖的情况,就从后往前复制
    if (p_dst > p_src && p_dst < p_src + n){
       p_dst = p_dst + n - 1;
       p_src = p_src + n - 1;
       while (n--) *p_dst-- = *p_src--;
   } else{
         while (n--) *p_dst++ = *p_src++;
     }
     
     return dst;
 }
 //4字节搬运版本:),32位内存对齐情况下,性能比单字节版本高不少
void* my_memcpy_4byte(void* dst, const void* src, int n) {
    //异常情况
    if (dst == NULL || src == NULL || n <= 0) return NULL;

    int* p_dst = (int*)dst;
    int* p_src = (int*)src;

    int len_4byte = n / 4;
    int len_byte = n % 4;

    char* tmp_src;
    char* tmp_dst;

    //考虑内存覆盖的情况,就从后往前复制
    if (p_dst > p_src&& (char*)p_dst < (char*)p_src + n) {
        tmp_dst = (char*)p_dst + n - 1;
        tmp_src = (char*)p_src + n - 1;

        while (len_byte--) *tmp_dst-- = *tmp_src--;
        //因为int*和char*步长不同,所以在强转之前要移动到合适的地方,这里++移动一个字节
        tmp_dst++;
        tmp_src++;
        p_dst = (int*)tmp_dst;
        p_src = (int*)tmp_src;
        //现在移动到了4个字节对齐的最后一个块的开头,这里--移动4个字节
        p_dst--;
        p_src--;
        while (len_4byte--) *p_dst-- = *p_src--;

    }
    else {
        while(len_4byte--) *p_dst++ = *p_src++;

        tmp_dst = (char*)p_dst;
        tmp_src = (char*)p_src;

        while (len_byte--) *tmp_dst++ = *tmp_src++;
    }

    return dst;
}

3、strcpy的实现

/**
 * @brief  将含有'\0'结束符的字符串从src复制到dst
 *
 * @param dst 	目标地址
 * @param src   源地址
 *
 *
 * @returns   
 *      成功: 目标字符串地址ret
 *      失败:NULL
 */
char* my_strcpy(char *dst, const char *src)
{
    //异常情况
    if (dst == NULL || src == NULL) return NULL;
    
    char* ret = dst;
    my_memcpy_byte(dst, src, strlen(src)+1);
    
    return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值