模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数

news/2024/11/29 20:47:59/
  • 前言:C语言中拥有非常多的库函数,仅仅知道它们是不够的,在知道它们的原理后,去模拟实现它能够帮助我们更好的掌握这些库函数。
    PS(在面试时,部分企业会让你来模拟实现一些库函数)

文章目录:模拟库函数的实现

  • 模拟实现strcmp
  • 模拟实现strcat
  • 模拟实现strstr
  • 模拟实现memcpy
  • 模拟实现memmove
    • 序言

查找库函数的网站

模拟实现strcmp

在模拟实现一个库函数之前,我们要先了解这个库函数的作用
这里我们可以通过这个查看C语言库函数的网站去查找:查找库函数
在这里插入图片描述
由此我们可以知道,strcmp的作用是将俩个字符串相比较,如果前者比后者长则返回大于0的数,反正则返回小于0的数,相等则返回等于0的数

代码实现思路:

分为三种情况:
①俩者所有字符全部相等 --> 返回0
②前者比后者小 --> 返回 -1
③前者比后者大 --> 返回1

代码实现:

#include <stdio.h>
#include <assert.h>
//模拟实现strcmp
int my_strcmp(const char* str1, const char* str2)//用const修饰防止传过来的指针值被修改
{assert(str1 && str2);//放在传过来的是空指针while (*str1++ == *str2++)//如果字符相等则进入循环看它们是否一一对应相等//如果不相等则跳出循环{if (*str1 == '\0')//如果*str1等于'\0'时,说明俩个字符串全部遍历完并且一一对应相等return 0;}if (*str1 > *str2)//如果不相等判断字符的大小,前置大则返回1return 1;elsereturn -1;
}
int main()
{char arr1[100] = {0};char arr2[100] = {0};gets(arr1);gets(arr2);int ret = my_strcmp(arr1, arr2);//保存返回值printf("%d\n", ret);return 0;
}

运行结果:
在这里插入图片描述

模拟实现strcat

还是一样的,在实现一个库函数之前,先了解该库函数的作用
在这里插入图片描述
注:将一个字符串,拼接到另一个字符串后面,该字符串不能是同一个字符串,并返回目标字符串的地址。

代码实现思路:

  • 找到目标空间地址的尾部
  • 将另一个字符串衔接上去
    代码实现:
//模拟实现strcat
char* my_strcat(char* str1, char* str2)
{//1.找到目标地址的尾部//2.衔接上去assert(str1 && str2);char* tmp = str1;//保留目标空间的起始地址while (*str1++)//找到目标地址的尾部'\0'{if (*str1 == '\0')//找到'\0'{while ( *str1++ = *str2++)//将地址衔接上去{;}}}return tmp;
}
int main()
{char arr1[100] = {0};char arr2[100] = {0};gets(arr1);gets(arr2);my_strcat(arr1, arr2);printf("%s\n", arr1);return 0;
}

运行结果:
在这里插入图片描述

模拟实现strstr

工欲善其事,必先利其器。如果我们想做好一件事,首先就要做好充分的准备工作。所以我们先了解其作用再来实现!
在这里插入图片描述
其作用是:在一个字符串中,找另一个字符串,如果没有找到则返回NULL,找到了就返回该字符串,并将原函数中该字符串后面的结果一并输出。

代码实现思路:

s1,s2(都是俩个字符串的指针)代表在s1中找s2
在这里插入图片描述
如果我们让s1,s2直接向匹配我们会发现,我们哪怕找到了想对应的字符,但是由于s1是不断的在往后走,我们并不能直接找到字符在相等的时候的位置,此时我们想要在通过原本的指针去找到相等的起始位置是十分困难的。因此,我们需要在引入一个指针去帮住我们记录下当俩个字符串完全相等的时候的起始地址。
在这里插入图片描述
我们让指针cp帮我们早到原本的地址,让s1去判断是否相等,让字符完全匹配时,返回cp的地址即可在这里插入图片描述

代码实现:

//模拟实现strstr
const char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp;//记录开始匹配的位置const char* s1;//记录str1的位置const char* s2;//记录str2的位置if (*str2 == '\0'){return str1;}cp = str1;//让cp去记录开始匹配的位置while (*cp){s1 = cp;s2 = str2;//让s2代替原本的str2去动while (*s1 && *s2 && *s1 == *s2)//s1,s2 !='\0' 并且s1 == s2{//找到它们的相同值,看他是否对应s1++;s2++;}if(*s2 == '\0')//如果全部找完,发现s2是'\0'说明找到了{return cp;//返回之前所留的cp记录的就是一开始的位置}cp++;//如果没有找到,就让cp往后加一继续重复刚刚的过程}return NULL;//如果全部运行了都没找到说明没有找到,返回空指针;
}
int main()
{char arr1[] = "mnabbbefghij";char arr2[] = "bbb";char* ret = my_strstr(arr1, arr2);if (ret == NULL){printf("找不到\n");}else{printf("%s\n", ret);}return 0;
}

运行结果:
在这里插入图片描述

模拟实现memcpy

依然来先看该库函数的作用:在这里插入图片描述
可以将任意同类型的数据,拷贝到另一个同类型的数据中去,但不能拷贝重叠内存

代码实现思路:

首先在实现的过程中,我们要知道,我们并不知道使用者会传过来什么类型的数据,因此我们在实现的过程中用俩个 void* 类型的指针来接受,并且我们要让使用者传过来他所需要拷贝的数据有多少字节。为什么需要知道字节?因为我们并不知道它的类型,我们将传过来的地址转换成char*类型,让它一次加1走一个字节俩俩交换,就能实现任意数据的交互了。
在这里插入图片描述

代码实现:

//模拟实现memcpy -- 不重叠的内存拷贝可以使用memcpy 
void* my_memcpy(void* arr1, const void* arr2, size_t num)
{char* tmp = arr1;assert(arr1 && arr2);while (num--){*(char*)arr1 = *(char*)arr2;//强制类型转换是一种临时变量arr1 = (char*)arr1 + 1;//让它们一次走一个字节,走一次交换换一次arr2 = (char*)arr2 + 1;}//全部字节交换完成后它们的地址也就全部交换完成了return tmp;
}
int main()
{int arr1[] = { 1,2,3,4,5,6 };int arr2[] = { 0,9,2,2,9 };my_memcpy(arr1, arr2, 16);int i = 0;for (i = 0; i < 6; i++){printf("%d ", arr1[i]);}return 0;
}

运行结果:在这里插入图片描述

模拟实现memmove

还是老规矩,运行代码之前先来看它的作用
在这里插入图片描述
前面我们说讲的memcpy可以拷贝同类型的数据,但不能拷贝重叠内存,而这个库函数就可以完美实现拷贝重叠内存

代码实现思路:

我们要知道在同一个数据中拷贝数据的时候会出现俩种情况:
①把低地址的值覆盖到高低址在这里插入图片描述
②把高地址的值覆盖到低地址
因此我们要对俩种情况进行分类讨论

代码实现:

//模拟实现memmove -- 可以拷贝重叠内存
void* my_memove(void* dest, void* src, size_t sz)
{char* tmp = dest;assert(dest && src);if (dest < src)//分俩种情况{//从前向后while (sz--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//从后往前while (sz--){*((char*)dest+sz) = *((char*)src + sz);// 让src与dest找到最后一个数,从后往前赋值}}return tmp;
}
int main()
{int arr[] = { 1,3,2,7,8 };my_memove(arr+2, arr , 12);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr[i]);}return 0;
}

运行结果:
在这里插入图片描述

序言

成大事不在于力量的大小,而在于能坚持多久。希望各位也能每天坚持学习,能够坚持也就是一种最大的天赋!如若写的不好的地方也希望各位指出。


http://www.ppmy.cn/news/1129236.html

相关文章

RISC-V 基础指令汇总

加载指令 存储指令 PC寻址指令 auipc rd, imm这条指令把 imm &#xff08;立即数&#xff09;左移12位并带符号扩展到64位后&#xff0c;得到一个新的立即数&#xff0c;这个新的立即数是一个有符号的立即数&#xff0c;再加上当前 PC 值&#xff0c;然后存储到 rd 寄存器中。…

Vovsoft Text Edit Plus 专业文本编辑器工具软件:简洁高效的创作利器

作为一名专业软件评测人员&#xff0c;我有幸使用了一款备受赞誉的文本编辑器工具软件——Vovsoft Text Edit Plus。在这篇评测中&#xff0c;我将客观、细致地分析它的实用性和使用场景&#xff0c;同时揭示它的优缺点&#xff0c;帮助您更好地了解这款软件。 第一部分&#x…

贪心算法-点灯问题

1、题目描述 给定一个字符串str&#xff0c;只由 ‘X’ 和 ‘.’ 两种字符构成。‘X’ 表示墙&#xff0c;不能放灯&#xff0c;点亮不点亮都可&#xff1b;’.’ 表示居民点&#xff0c;可以放灯&#xff0c;需要点亮。如果灯放在i位置&#xff0c;可以让 i-1&#xff0c;i 和…

目标检测YOLO实战应用案例100讲-面向辅助驾驶的道路目标检测

目录 前言 国内外研究现状 机器学习目标检测算法研究现状

0x84加密数据传输服务

为了在安全模式下实现一些诊断服务&#xff0c;在服务端和客户端应用程序之间添加了Security sub-layer。在客户端与服务端之间进行诊断服务数据传输有两种方法&#xff1a; 1、非安全模式下数据传输   应用程序使用诊断服务(diagnostic Services)和应用层服务原语(Applicati…

基于微信小程序的宠物寄养平台小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

网络爬虫--伪装浏览器

从用户请求的Headers反反爬 在访问某些网站的时候&#xff0c;网站通常会用判断访问是否带有头文件来鉴别该访问是否为爬虫&#xff0c;用来作为反爬取的一种策略。很多网站都会对Headers的User-Agent进行检测&#xff0c;还有一部分网站会对Referer进行检测&#xff08;一些资…

【MATLAB源码-第40期】基于matlab的D*(Dstar)算法栅格路径规划仿真。

1、算法描述 D*算法路径规划 D*算法&#xff08;Dynamic A*&#xff09;是A*算法的一种变种&#xff0c;主要用于在地图中的障碍物信息发生变化时重新计算路径&#xff0c;而不需要从头开始。该算法适用于那些只有部分信息已知的环境中。 工作原理&#xff1a; 1. D*算法首先…