模拟实现字符串函数(长度受限制的详讲)
上次发布了长度不受限制的字符串函数的模拟实现方法,这次就给大家说说长度受限制的字符串函数。首先,长度受限制和不受限制有什么区别呢?其实从某种意义上来讲,长度受限制的字符串函数比长度不受限制的字符串安全,为什么安全呢?下面就让我们看看长度受限制的字符串函数到底在哪安全了,安全到哪了,
1.strncpy
首先来看这个函数的前两个参数都不用说(如果有不懂的小伙伴可以看我上一篇博客),第三个参数的意思是拷贝几个字符,返回类型就不用说了吧,直接看库里面函数的代码以及调试过程以及打印:
//int main()
//{
// char arr[] = "abcdef";
// char arr1[20] = "xxxxxxxxxxxxxx";
// char* p = strncpy(arr1, arr, 12);
// printf("%s", p);
// return 0;
//}
其实仔细观察,你会发现我们要拷贝的字符个数大于了要拷贝字符串的长度,那么,大家想想,会发生什么,我们看到调试的时候已经拷贝完成,但是拷贝完成之后,多余的那些字符怎么办呢?其实,再用strncpy时,多余的字符会用‘\0’来代替。
那么我们看一下我们自己模拟实现的这个函数到底与库函数的功能项不相同呢?看下面:
char* my_strncpy(char* dest, const char* src, size_t num)
{assert(dest && src);char* tem = dest;while (num){if (*src != '\0'){*dest++ = *src++;num--;}else{*dest++ = '\0';num--;}}return tem;
}
int main()
{char arr[] = "abcdef";char arr1[20] = "xxxxxxxxxxxxxxxxx";char* p = my_strncpy(arr1, arr, 12);printf("%s", p);return 0;
}
我们可以看到的是我们模拟实现的这个函数功能与库里的函数功能相同,调试过程也是相同的,多余字符用了‘\0’来代替。这个函数的注意事项和strcpy的一样,就不在这里多说了,而我想说说他与strcpy的区别是:首先,strcpy是拷贝整个字符串,不受长度限制,只要使用,就是整个字符串拷贝,而strncpy是受字符串长度限制的,他一般是会看第三个参数是几就拷贝几个字符过去,所以这个要注意,如果要是拷贝的字符个数小于源头字符串的长度的话,拷贝完之后是不加‘\0’的,举个例子:
char* my_strncpy(char* dest, const char* src, size_t num)
{assert(dest && src);char* tem = dest;while (num){if (*src != '\0'){*dest++ = *src++;num--;}else{*dest++ = '\0';num--;}}return tem;
}
int main()
{char arr[] = "abcdef";char arr1[20] = "xxxxxxxxxxxxxxxxx";char* p = my_strncpy(arr1, arr, 3);printf("%s", p);return 0;
}
就用我们自己实现的这个函数来写举例子吧,如果拷贝的字符数是3个,那么此时的arr1打印出来是这个结果
充分说明了在拷贝的时候没有加‘\0’,说几个就是几个。
2.strncat
这个函数的返回类型,形参与上面相同,就不在多说,他的功能是追加字符串,先上代码理解一下这个函数。
int main()
{char arr[100] = "hello xxxxxxxxxx";char arr1[] = "world";strncat(arr, arr1, 4);printf("%s", arr);return 0;
}
要注意的是这个函数在追加完限制的长度后,会自动加上\0,这个是与strcat不同的,下面我们来自己实现一下这个函数,
char* my_strcat(char* dest, const char* src, size_t num)
{assert(dest && src);char* tem = dest;while (*dest++);dest--;while (num){if (*src){*dest++ = *src++;num--;}else{break;}}*dest = '\0';return tem;
}
int main()
{char arr[20] = "hello \0xxxxxxx";char arr1[] = "world";char* p = my_strcat(arr, arr1, 4);printf("%s", p);return 0;
}
这个结果与我们想要的看到的结果正是一样的,如果要追加长度大于我们圆头的字符串,那么就把整个源头字符串追加上去就好,多余的不会像strncpy一样补'\0',感兴趣的可以自己测试一下,这个函数的注意事项与strcat也是基本一样,这里就不再多说。
3.strncmp
这个函数与strcmp的参数与返回类型一样,这里不再多说,这个函数的功能就是对比字符串的大小,具体规则是什么呢?我们来仔细看看库里的
int main()
{char arr[20] = "abcd";int t = strncmp(arr, "hjk", 100);printf("%d", t);return 0;
}
这个函数其实个人感觉也看不出什么,因为这个没有改变两个字符串的内容,所以就不在调试,直接看结果吧,
对比结果很简单,这个不用我说,一眼就可以看出来,直接看看我们的模拟实现代码吧
int my_strncmp(const char* str, const char* str1,size_t num)
{assert(str && str1);while (num){if (*str == *str1){str++;str1++;num--;}else{return *str - *str1;}}return 0;
}
int main()
{char arr[] = "hfjklsadhfjksdhajkf";char arr1[20] = "hfjklsadhfjksdhajk";int ret = my_strncmp(arr, arr1,19);printf("%d", ret);return 0;
}
这个实现过程思路和strcmp其实非常类似,唯一不同的就是,strcmp循环出来以后要判断,而strncmp这个函数出来以后就不需要判断,他们的循环条件不一样。我们来看看打印结果
用库里的函数打印的结果是1,而我用的返回结果是*str-*str1,所以就返回的是102,还是根据个人喜好来写,返回1没有错,但是库里函数明显显示的是返回大于0小于0等于0的数,所以只要符合这个规则就可以。
总结:长度受限制和不受限制的字符串函数其实注意事项是差不多的,都是一一对应的,那么,我们现在来说一下为什么受限制的比不受限制的函数相对来说是安全的呢?打个比方,就以strcpy和strncpy来做比较,在使用时,如果我们不小心拷贝的时候,目的地的空间大小不够了,那么此时他还是会拷贝,但是打印的时候才会出现栈被破坏的通知(这个是strcpy),而strncpy这个函数就比较安全了,因为他受长度的限制,所以每次打印的时候,(如果不是故意的话)不会出现站被破坏的情况。其他的几个函数其实和这个是一样的道理,慢慢想就可以理解,这里不再多说。
最后,如果大家感觉又用的话,就点一下赞吧!支持一下!谢谢!
相关文章:

模拟实现字符串函数(长度受限制的详讲)
上次发布了长度不受限制的字符串函数的模拟实现方法,这次就给大家说说长度受限制的字符串函数。首先,长度受限制和不受限制有什么区别呢?其实从某种意义上来讲,长度受限制的字符串函数比长度不受限制的字符串安全,为什…...

分布式ID生成方案总结
什么是分布式 ID 分布式 ID 是指,在分布式环境下可用于对数据进行标识且易存储的全局唯一的 ID 标识。 为什么需要分布式 ID 对于单体系统来说,主键ID可能会常用主键自动的方式进行设置,这种ID生成方法在单体项目是可行的。 对于分布式系统…...
极智AI | 百度推出文心一言,对标ChatGPT功力几成
欢迎关注我,获取我的更多经验分享,极智传送《极智AI | 百度推出文心一言,对标 ChatGPT 功力几成》 大家好,我是极智视界,本文介绍一下 百度今日推出文心一言,对标ChatGPT功力几成。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https…...

CleanMyMac X最新版本4.12.6
系统要求macOS 10.12及更高,M1机型及最新macOS 13 CleanMyMac可以为Mac腾出空间,软件已经更新到CleanMyMac X支持最新版Mac系统。CleanMyMac具有一系列巧妙的新功能,可让您安全,智能地扫描和清理整个系统,删除大量未使…...

替代notepad++,notepad--介绍及插件cmake编译
Notepad 是一个文本编辑器小软件,用来替代windows自带的记事本。然而Notepad软件的作者是台湾省人,其具有明显的gd/jd/td倾向,如果你不赞同他的观点,Notepad将会在你的源码里面插入随机字符。推荐一款国产的开源跨平台软件NDD(not…...
机器学习笔记之集成学习(四)Gradient Boosting
机器学习笔记之集成学习——Gradient Boosting引言回顾:Boosting\text{Boosting}Boosting算法思想与AdaBoost\text{AdaBoost}AdaBoostGradient Boosting\text{Gradient Boosting}Gradient Boosting算法介绍场景构建算法过程迭代过程与梯度下降法之间的关联关系引言 …...

WPA渗透-pyrit:batch-table加速attack_db模块加速_“attack_db”模块加速
WPA渗透-pyrit:batch-table加速attack_db模块加速_“attack_db”模块加速 1.渗透WIFI 1.导入密码字典 pyrit -i 字典文件 import_passwords -i:输入的文件名 import_passwords:从类文件源导入密码。pyrit -i pwd.txt import_passwords2.导…...
kotlin第二部分复习纪要
扩展函数。 例如: fun Context.toast(msg: String, length: Int Toast.LENGTH_SHORT){Toast.makeText(this, msg, length).show() } 使用 val activity: Context? getActivity() activity?.toast("Hello world!") activity?.toast("Hello worl…...

代码随想录--链表--删除链表第n个节点题型、链表相交题型
删除链表第n个节点题型 链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点 (opens new window) 这道题我一开始想的是,倒数第n个节点,链表不方便往前找,那就从链表头结点开始找链表长度减n,这时候就是…...

一起来学5G终端射频标准(In-band emissions-2)
上一篇我们列出了IBE的测试要求表格,今天我们详细说一下IBE如何测量计算,以及CA/NR-DC/SUL/UL-MIMO/V2X/Tx Diversity模式下的IBE情况。01—IBE如何测量和计算IBE的测试是对落入到未被分配的RB的干扰的测量,为12个子载波的平均发射功率&#…...
硬刚ChatGPT,中国版ChatGPT“狂飙”的机会在哪儿?
整体来讲,个人的态度是积极的。 ChatGPT、文心一言 都是在多重因素及大量 AI 模型/数据 长时间累积的成果,不是一蹴而就,立竿见影的功能产品。两者产生的基础和背景均不相同,各有优劣,不存在强行对比的概念。 以下是 …...

ReactNative——导航器createBottomTabNavigator(底部标签导航器篇)
上一篇有讲到堆栈式导航器的写法,点这里->堆栈式导航器标签导航器官网链接先安装依赖包yarn add react-navigation/bottom-tabs接着在src/navigator文件夹下新建BottomTabs.tsx文件,写法跟堆栈式导航器类似的~import React from react; import { NavigationConta…...

【数据结构】带头双向循环链表的实现
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...

软件开发的权限系统功能模块设计,分享主流的九种常见权限模型
软件系统的权限控制几乎是非常常见且必备的,这篇文章整理下常见的九种模型,几乎基本够你用了,主流的权限模型主要有以下9种: 1、ACL模型 访问控制列表 2、DAC模型 自主访问控制 3、MAC模型 强制访问控制 4、ABAC模型 基于属性的访…...

CSS3-数据可视化
2D动画 - transform CSS3 transform属性允许你旋转,缩放,倾斜或平移给定元素。 Transform是形变的意思(通常也叫变换),transformer就是变形金刚 常见的函数transform function有: 平移:transl…...

硬件系统工程师宝典(15)-----PCB上的EMC设计,“拿捏了”
各位同学大家好,欢迎继续做客电子工程学习圈,今天我们继续来讲这本书,硬件系统工程师宝典。上篇我们说到PCB常用的多层板叠层结构,综合成本、性能、需求考虑选择不同的叠层结构。今天我们来看看为提高EMC性能,在PCB设计…...

vue3滚动条滚动后元素固定
代码地址:https://gitee.com/zzhua195/easyblog-web-vuee Framework.vue 在这个布局组件中,监听main的滚动事件,获取滚动的距离,将它存入store,以便其它组件能够共享,监听到 <template><div c…...

新吲哚菁绿染料IR-825 NHS,IR825 NHS ester,IR825 SE,IR-825 活性酯,用于科研实验研究和临床
IR825 NHS理论分析:中文名:新吲哚菁绿-琥珀酰亚胺酯,IR-825 琥珀酰亚胺酯,IR-825 活性酯英文名:IR825 NHS,IR-825 NHS,IR825 NHS ester,IR825 SECAS号:N/AIR825 NHS产品详…...
GO语言--接口(interface)的定义及使用
接口定义 接口也是一种数据类型,它代表一组方法的集合。 接口是非侵入式的。即接口设计者无需知道接口被哪些类型实现,而接口使用者只需知道实现怎样的接口,并且无须指明实现哪一个接口。编译器在编译时就会知道哪个类型实现哪个接口&#…...
【Python语言基础】——Python MongoDB 查询
Python语言基础——Python MongoDB 查询 文章目录 Python语言基础——Python MongoDB 查询一、Python MongoDB 查询一、Python MongoDB 查询 筛选结果 在集合中查找文档时,您能够使用 query 对象过滤结果。 find() 方法的第一个参数是 query 对象,用于限定搜索。 实例 查找地…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...