模拟实现库函数,strtsr,memmove.

简介: <1>主页:C语言的前男友<2>知识讲解:模拟实现 库函数 strstr,memmove<3>创作者:C语言的前男友<4>开发环境:Visual Studio 2022<5>前言:学习了strstr,memnove等库里面的内存相关的函数,功能非常的强大。今天我们来模拟实现一下。

ece52fa0361742dbba5c93cdd0af2825.png


一.strtsr()

(1)strtsr介绍:


b2a762777a31423989a3406eda9c9761.png


strstr函数是库里面提供的查找字串的的一个函数,返回值是一个char*的指针,指针指向的是子串在原串中的位置指针,如果没有查找到的话,就会返回NULL。


(2)使用演示

#include<stdio.h>
#include<string.h>
int main()
{
  char str1[] = "abcdefghij";
  char* str2 = "cde";
  char* str3 = "abp";
  //返回str2在str1中的位置指针,即返回"cdefhij";首元素的指针
  char* rep = strstr(str1, str2);
  char *rep1 = strstr(str1, str3);
  if (rep == NULL)
  {
    printf("没找到str2\n");
  }
  else
  {
    printf("找到了str2:%s\n",rep);
  }
  if (rep1 == NULL)
  {
    printf("没找到str3\n");
  }
  else
  {
    printf("找到了str2%s\n", rep1);
  }
  return 0;
}

4cdd1aaa72c5441eadbef5d75b69a1d1.png


(3)模拟实现:


fb8176b7b1b946ad9a617bc3a17cb334.png


主要实现思路就是,从p指针位置,s1开始和s2匹配,如果 s1 和 s2 指向的字符相同,那就s1和s2都挪向下一个字符,如果s1和s2指向的字符不相同,那就意味着此次匹配失败,后面也就没有必要经行匹配了,直接 p 向后挪一个字符,进入下一次的匹配。直到s2指针 ‘ \0 ’ 时。匹配成功结束,或者 s1 也指向 ‘ \0 ’ 了,原串都匹配玩了,自然也就结束了。


d1556a15dc884730ba91effa0ca9ef24.png


(4) 代码:

char* my_strstr(char* str1, char* str2)
{
  char* p = str1;
  while (*p)
  {
    char* s1 = p;
    char* s2 = str2;
    //从p的位置开始与s1 和 s2 开始匹配。
    while (*s2 != '\0' && *s1 != '\0' && *s1 == *s2)
    {
      s1++;
      s2++;
    }
    //当匹配出来时,只有s2 已经指向‘ \0 ’,才说明匹配成功
    if (*s2 == '\0')
    {
      return p;
    }
    p++;
  }
  //当原串都匹配完了,那就是没有原串中没有子串,返回NULL;
  return NULL;
}

(5)代码效果:


d1b1d84a29fd4afabcaee67b61abc092.png


二.memmove()

(1)memmove介绍


0b2a1745aa704dc6b7ea6aeb9cc9e7ab.png


void * memmove ( void * destination, const void * source, size_t num );

memmove是将,source 后面的 num 个字节的数据,拷贝到 destination 处,而且源内存块和目标内存块重叠也是可以处理的。


(2)memmove演示:

1.空间不重叠拷贝

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print(int* arr, int n)
{
  for (int i = 0; i < n; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}
int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
  int arr2[10] = { 0 };
  print(arr2, 10);
    //将arr1中的前 4 * 5 = 20 个字节拷贝到arr2中,
  memmove(arr2, arr1, 20);
  print(arr2, 10);
  return 0;
}


2fe07ada424142b182ea99b04f1902d3.png


2.空间重叠的拷贝

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print(int* arr, int n)
{
  for (int i = 0; i < n; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}
int main()
{
  int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
  int arr2[10] = { 0 };
  print(arr1, 10);
  //将arr1后面的20个字节,拷贝到 arr1+2 后面20字节 
  //arr1后面的20个字节就是 1 2 3 4 5
  //arr1+2后面20个字节就是 3 4 5 6 7
  memmove(arr1+2, arr1, 20);
  print(arr1, 10);
  return 0;
}


f3cd273cc18a4a9eb4817cf3ed07163f.png


(3)模拟实现memmove

首先memmove就是具有,对重叠空间的处理能力的。所以我们在模拟实现之前就要弄清楚,重叠空间拷贝时会有那些意想不到的结果。


ac64cefc1d4d4b56846deb18c15e60ba.png


b69de4c3c7aa4033844f643b8d533fed.png


所以:


当我们是将后面的间的内容拷贝到前面的空间时,就需要从前往后拷贝。


当我们是将前面空间的内容拷贝到后面的空间时,就需要从后往前拷贝。


(4)代码:

#include<stdio.h>
#include<string.h>
#include<assert.h>
void print(int* arr, int n)
{
  for (int i = 0; i < n; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}
//参数设计:dest->目标空间   source->原数据空间  num->拷贝大小(单位:字节);  
void* my_memmove(void*dest,const void*source,size_t num)
{
  void* ret = dest;
  assert(dest && source);
  //如果目标的空间在原数据的前面,那就从前往后拷贝。
  if (dest < source)
  {
    while (num--)
    {
      *((char*)dest) = *((char*)source);
      dest = (char*)dest + 1;
      source = (char*)source + 1;
    }
  }
  //如果目标空间在原数据的后面,那么就从后往前拷贝。
  else
  {
    while (num--)
    {
      *((char*)dest + num) = *((char*)source + num);
    }
  }
  return ret;
}
int main()
{
  int arr[] = {1,2,3,4,5,6,7,8,9,10};
  print(arr, 10);
  my_memmove(arr , arr+2, 20);
  print(arr, 10);
}


(5)运行效果:


5032c42ec2fe4890bf6d1c5845185366.png

3b32ed64e9824354b2f8769a167c4d41.png


最后:

因为心中有梦,所以暗里有光,遥遥无期,那又怎样,踮起脚尖,就更接近阳光。


5a967879903c4aefa33b1de40b3c8bb8.png


相关文章
|
监控 安全 Linux
在Linux中,如何配置VPN服务?
在Linux中,如何配置VPN服务?
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
352 5
|
设计模式 安全 Java
趣解设计模式之《小王的学习秘籍》
趣解设计模式之《小王的学习秘籍》
284 1
|
存储 弹性计算 Cloud Native
《云上业务稳定性保障实践白皮书》——五.行业客户稳定性保障实践——5.1 游戏业务稳定性保障——5.1.2 游戏容器化部署最佳实践(2)
《云上业务稳定性保障实践白皮书》——五.行业客户稳定性保障实践——5.1 游戏业务稳定性保障——5.1.2 游戏容器化部署最佳实践(2)
326 0
|
区块链 数据安全/隐私保护
区块链101:公开和许可的区块链有什么区别?
区块链101:公开和许可的区块链有什么区别?
|
前端开发 JavaScript
JavaWeb博客系统
JavaWeb博客系统
211 0
|
API SEO
做SAAS需要耐得住寂寞(1)
做SAAS需要耐得住寂寞
140 0
|
关系型数据库 MySQL 索引
开发指南—DDL语句—分库分表语法—DROP INDEX
本文介绍了如何删除局部索引和全局二级索引
|
SQL Oracle 算法
Oracle MySQL相关工具replace操作实现方式区别
本文列举MySQL、Oracle、常用数据导入工具碰到主键冲突、唯一约束、以及其他对重复数据、已有数据的处理区别,并介绍MySQL、Oracle replace相关语句实现区别。 由此可见在实际使用不同数据库过程中,还是有许多差别,需要大家细心留意。
943 0
|
数据库 索引 SQL
read by other session的优化记录
【背景】以下是一个ERP数据库的AWR报告,初看数据库挺繁忙的,DB Time/Elapsed的比值接近20,再深入往下看发现数据库的read by other session事件明显,以下是经过一系列的分析解决了read by other session等待事件的问题;   Top 5等待事件   【问题分析一】read by other session产生的原因:发生在一个数据块正在被读进buffer,而其它session此时也要请求这个数据块的时候。
1122 0