【C语言】strcat、strncat详解并模拟实现
1.库函数strcat:
函数声明:char* strcat(char* strdestination, const char* strsource);
提示:源字符串在函数实现过程中不修改其内容,所以加const修饰更安全!
strdestination: 目标字符串
strsource:源字符串
函数介绍:strcat是连接/追加字符串的函数,两个形参都是指针,函数最终返回一个指向目标字符串首元素地址的指针。
函数实现:
- 首先strcat函数会一直在目标字符串中往后数,直到指针指向目标字符串中的'\0'
- 源字符串赋值给目标字符串,源字符串的第一个字符将目标字符串中指针指向的'\0'替代掉,并将自己的‘\0’赋值到目标字符串当中
- 打印目标字符串
应用举例:
#include <stdio.h>
#include <string.h>
#include <windows.h>int main()
{char dest[20] = "Hello ";//定义目标字符串空间可修改char src[] = "world";printf("%s\n",strcat(dest,src));system("pause");return 0;
}
模拟实现:
#include <stdio.h>
#include <string.h>
#include <assert.h>char* my_strcat(char* strdestination,const char* strsource)//源字符串不用修改,加const防止其被意外修改
{assert(strdestination != NULL && strsource != NULL);//对源字符串和目标字符串进行断言,防止空指针char* reverse_back = strdestination;//提前记录保存目标字符串首地址while (*strdestination)//让指针指向目标字符串的'\0',当指针指向‘\0’的地址时,再解引用后为0,跳出循环{strdestination++;}while (*strdestination++ = *strsource++);//将源字符串赋值给目标字符串,当源字符串的‘\0’赋值给目标字符串后跳出循环return reverse_back;//返回目标字符串的首地址
}int main()
{char dest[20] = "Hello ";//定义目标字符串char src[] = "world";//定义源字符串printf("%s\n", my_strcat(dest, src));//调用函数并打印return 0;
}
注意:
- 指针strdestination所指向的目标空间必须要能容纳下两个字符串连接后的大小。
- 源字符串必须以 '\0' 结尾。
- 目标空间必须可修改。
- 自己无法直接追加自己。
反向验证:1.
int main()
{char arr1[5] = "Hello ";//定义字符串,内存太小,无法容纳两个字符串连接后的大小char arr2[] = "world";printf("%s\n",strcat(arr1,arr2));return 0;
}
运行结果:
由此,不难看出,当目标空间太小会发生数组溢出,导致程序出错!
在反向验证2前,首先我们要学会strcat是如何追加/连接字符串的:
int main()
{char arr1[20] = "Hello \0*********";//巧妙定义字符串,可以观察到源字符串在目标字符串当中的赋值情况char arr2[] = "world";printf("%s\n", strcat(arr1, arr2));return 0;
}
以上代码的调试监视窗口:
观察图片就可以明白,源字符串会将目标字符串的‘\0’替代掉,并且会将自己的‘\0’赋值到目标字符串,那么如果源字符串没有将‘\0’赋值给目标字符串会出现什么情况呢?接下来就开始验证!
反向验证:2.
int main()
{char arr1[20] = "Hello \0*********";char arr2[] = "world";char* pa = strcat(arr1, arr2);arr1[11] = '#';//当我们把从arr2赋值给arr1的'\0'修改成字符'#',后观察调试结果printf("%s\n",arr1);return 0;
}
从上面的运行结果就不难看出,函数会持续往后读取,所以源字符串必须要有‘\0’,否则在打印字符串的时候就会发生非法越界访问,导致出错!
反向验证:3.
int main()
{char *ps = "Hello ";//定义目标字符串空间不可修改char arr2[] = "world";printf("%s\n",strcat(ps, arr2));return 0;
}
不难发现,当目标空间无法修改的时候,程序就会挂掉!
反向验证:4.
int main()
{char arr1[20] = "abcdef";printf("%s\n", strcat(arr1, arr1));//自己追加自己return 0;
}
调试过程:
追加字符串时函数要在源字符串当中寻找‘\0’来结束追加,而这里的源字符串其实就是目标字符串,结合上述图片内容就不难发现,源字符串在追加过程当中用字符‘a’覆盖了‘\0’,之后在追加过程当中就无法在源字符串当中寻找到‘\0’,程序就会持续运行,最终导致程序崩溃!
这时凸显出另一个库函数 strncat 的作用了.......
2.库函数strncat:
函数声明:char* strncat(char* strdestination, const char* strsource, size_t num);
提示1:源字符串在函数实现过程中不修改其内容,所以加const修饰更安全!
提示2:使用size_t目的是因为num只代表个数,不代表正负!
函数介绍:strncat函数将源字符串的前num个字符连接到目标字符串的末端,连接后的结果放在目标字符串当中,函数有三个形参,两个指针,一个无符号整型,函数返回一个指向目标字符串首元素地址的指针。
函数实现:
- 首先strncat函数会一直在目标字符串中往后数,直到指针指向目标字符串中的'\0'
- 把源字符串的前num个字符连接到目标字符串的末端,然后加上‘\0’
- 打印目标字符串
应用举例:
#include <stdio.h>#include <string.h>int main()
{char arr1[20] = "Hello ";//定义目标字符串char arr2[] = "world";//定义源字符串printf("%s\n", strncat(arr1, arr2, 3));//追加字符串并打印return 0;
}
模拟实现:
#include <stdio.h>
#include <string.h>
#include <assert.h>char* my_strncat(char* strdestination, const char* strsource, size_t num)//源字符串不用修改,加const防止其被意外修改
{assert(strdestination != NULL && strsource != NULL);//对源字符串和目标字符串进行断言,防止引入空指针char* reverse_back = strdestination;//提前记录保存目标字符串的首地址while (*strdestination)//让指针指向目标字符串的'\0'{strdestination++;}while (num--)//追加字符的个数{if ((*strdestination++ = *strsource++) == 0)//当追加字符的个数大于源字符串中字符的个数时,函数只会追加到源字符串的'\0',防止越界{return reverse_back;//返回目标字符串首元素的地址}}*strdestination = '\0';//当没有追加到源字符串的'\0'时,给目标字符串末尾添加一个'\0',防止打印越界return reverse_back;//返回目标字符串首元素的地址
}int main()
{char dest[20] = "Hello ";//定义目标字符串char src[] = "world";//定义源字符串printf("%s\n", my_strncat(dest, src, 3));//调用函数并打印return 0;
}
注意:
- 指针strdestination所指向的目标空间必须要能容纳下目标字符串和所追加的源字符串字符连接后的大小。
- 目标空间必须可修改。
以上注意事项在strcat函数部分都已举例,请返回参考!
在strncat函数运用的时,出现的情况:
- 当源字符串的长度大于num时,函数只会在目标字符串末尾追加源字符串的前num个字符,并且在这num个字符后面的位置添加一个'\0'字符。
- 当源字符串的长度小于num时,函数会检测到源字符串末尾的'\0',自动结束追加!
- 可以实现自己追加自己。
验证3.
#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "Hello ";printf("%s\n", strncat(arr1, arr1,5));return 0;
}
从运行结果可知,strncat函数是可以实现自己给自己追加,但会报一个警告!
因为strncat函数的两个指针都指向同一个数组,在函数运算过程当中,该数组内存储的字符一直在变化,所以函数会认为运用的这个字符串数组没有初始化变量!
本人大一新生一枚,写的不好和错的地方,大家可以指正出来,我们共同进步 。希望大家谅解!
如果大家觉得我写的还行,帮小编点一个免费的赞和关注,我会持续更新出更好的博客,谢谢大家!
【C语言】strcat、strncat详解并模拟实现相关推荐
- C语言strncpy函数详解及其模拟实现
char * strncpy ( char * destination, const char * source, size_t num ); strncpy函数是C语言中的内置函数之一,相较于str ...
- 【排序】什么都能排的C语言qsort排序详解【超详细的宝藏级别教程】深度理解qsort排序
[排序]什么都能排的C语言qsort排序详解[超详细的宝藏级别教程]深度理解qsort排序 作者: @小小Programmer 这是我的主页:@小小Programmer 在食用这篇博客之前,博主在这里 ...
- (转)C语言位运算详解
地址:http://www.cnblogs.com/911/archive/2008/05/20/1203477.html C语言位运算详解 作者:911 说明:本文参考了http://www2.ts ...
- R语言基础知识详解及概括
R语言基础知识详解及概括 目录 R语言基础知识详解及概括 R数据可视化示例 R语言进行数据创建
- c语言练习题及答案)(1),c语言练习题(带详解答案)1.pdf
c语言练习题(带详解答案)1 (-2) -1: 一单项选择题 /为求商运算符,该运算符能够对整型.字符.浮点等类型的数 据进行运算,5/2 2 1.(A )是构成C语言程序的基本单位. 11.如果 i ...
- python语言的格式框架_django框架模板语言使用方法详解
本文实例讲述了django框架模板语言使用方法.分享给大家供大家参考,具体如下: 模板功能 作用:生成html界面内容,模版致力于界面如何显示,而不是程序逻辑.模板不仅仅是一个html文件,还包括了页 ...
- C语言再学习 -- 详解C++/C 面试题 2
(经典)C语言测试:想成为嵌入式程序员应知道的0x10个基本问题. 参看:嵌入式程序员面试问题集锦 1.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define ...
- B-、B树详解及模拟实现
B-.B树详解及模拟实现 文章目录 B-.B树详解及模拟实现 一.B-树 二.B树 1.性质 2.特性解释 3.B树的插入操作 4. B树的删除操作 5.B树摸拟实现 一.B-树 B-树就是B树 二. ...
- python自动解析json_Python语言解析JSON详解
本文主要向大家介绍了Python语言解析JSON详解,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. JSON 函数使用 JSON 函数需要导入 json 库:import jso ...
最新文章
- MXNet中x.grad源码追溯
- 汇编:以字符形式给出数据
- 公钥密码--Elgamal
- ICLR 2020 | GAN是否真的判断出了数据的真假?
- 21个ui设计技巧,让你的设计不落伍
- LinkedHashSet类
- python单片机编程软件下载_Python开发例程大全
- AI、大数据、中台、AIoT、Fintech等十余场火热专题应有尽有,年度盛会BDTC 2019邀您共赴!...
- Thread多线程用法示例
- 选中菜单 android,Android支持:设计NavigationView选中的菜单子项
- 安卓应用性能调试和优化经验分享
- bootstrap 文字不换行
- 电子邮件的收件人、抄送、密送
- 微信铁通服务器地址,铁通dns服务器地址大全
- Azure NSG(安全组)
- 树莓派3B+温控风扇
- 【2021-07-16】堆糖小程序
- shiro-基本原理和逻辑配置
- Image Segmentation Using Deep Learning: A Survery
- Codeforces 776B 776C 程序(夏洛克专场)
热门文章
- 重磅新品3D打印机“智能微工厂”CP-01引全球关注,本周强势登陆
- ApacheCN 飞龙:对知乎上某 SB 的回复
- python对datetime排序_【python】时间戳、字典列表排序
- Unify学习笔记2
- circular linked listCLL(循环链表)
- C-TPAT认证咨询,当实体加入CTPAT时,将与CBP达成协议以保护供应链
- 【毕业设计】java停车场管理系统 停车管理系统
- 医疗平台在线咨询文本分析——爬取数据(一)
- 数据可视化大屏设计师,我不信你没有这些困惑!(上)
- 就地过年,别让加班费“就地蒸发”