⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:C语言初阶
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!
文章目录
- 前言
- 一、简介
- 1.认识strcpy
- 2.应用strcpy
- 3.监视分析
- 二、模拟实现strcpy
- 1.初步实现
- 2.输入空指针
- 3.assert
- 4.这阶段完整代码
- 三、返回值
- 1.返回类型
- 2.const
- 四、完整代码
- 总结
前言
strcpy函数其实大家并不陌生,但是每次用的时候要么就复制到字符串的地方不对,要么就出现错误,那到底该怎么用这个函数呢?接下来我将详细给大家讲解strcpy这个函数的本质和用法!
一、简介
1.认识strcpy
再认识这个函数之前,我先放一张图片供大家理解一下:
在MSDN中查一下这个函数,发现是从后面的数组复制一份复制到前面的数组,那当然,大家伙可能会问了,为什么有一个const被圈出来了,这个const很熟悉呀,之前见到过了,大家伙继续往后看,在文中我会跟大家详细解说一下这个const与指针配套起来的用法。
2.应用strcpy
先带大家看一看运用一下strcpy的奇效。
#include#includeint main() {char arr1[20] = "****************";char arr2[] = "hello";strcpy(arr1, arr2);printf("%s\n", arr1);return 0;}
看,运用了这个函数以后感觉是在是太方便了,能把arr2中的“hello\0”全部复制到arr1[20]里面去,唉,大家可能会问了,屏幕上显示的是hello啊,没有那个’\0’,大家继续往下面看,就立马能够理解了。
3.监视分析
先上几张图片让大家理解理解。
1.将*赋到arr1数组中。
2.将hello+’0’赋到arr2数组中。
3.进行复制的操作。
4.原理图
利用监视器看strcpy函数能够看到它的本质就是将后面数组里面的字符串+‘、0’拷贝到前面的数组中,但是为什么会有\0呢,这个很简单,arr[]={a,b,c,d}与arr[]=”abc”是有本质的区别的,后者多一个\0,大家可以去看看我以后写的关于数组的区分的博客哦!
二、模拟实现strcpy
1.初步实现
先上个代码:
代码1:这个代码很好理解,就先取数组的首地址并交换再往后加加,直到最后一个元素进行交换完退出循环。
#include//#includevoid my_strcpy(char* dest, char* src) {while (*src != '\0'){*dest++ = *src++;} *dest = *src; //拷贝\0}int main() {char arr1[20] = "****************";char arr2[] = "hello";my_strcpy(arr1, arr2);printf("%s\n", arr1);return 0;}
代码2:这个代码可以把\0直接打印出来,不需要最后一步加上交换一次\0。
#include//#includevoid my_strcpy(char* dest, char* src) {while (*dest++ = *src++) {;} }int main() {char arr1[20] = "****************";char arr2[] = "hello";my_strcpy(arr1, arr2);printf("%s\n", arr1);return 0;}
但这代码实现的看似没什么问题,可是也隐藏着一个很大的问题,数组是我已经定义好了的,但是,如果是在主函数里面输入NULL(空指针)呢?那让我们先来看看。
2.输入空指针
输入空指针后,编译器立马就报错了,所以,这是肯定不行的!那怎么解决呢?接下来上一串代码!
子函数里加了先判断输入的两个指针元素存不存在空指针,有空指针那就不进行后续操作。
#include//#includevoid my_strcpy(char* dest, char* src) {if (src == NULL || dest == NULL){return;}while (*dest++ = *src++) {;} }int main() {char arr1[20] = "****************";char* p = NULL;my_strcpy(arr1, p);printf("%s\n", arr1);return 0;}
大家想一个问题,如果一个程序员喝了点小酒醉了,只看到了这个程序可以直接运行,很开心的到老板那里邀功,老板说,你这做的啥!为什么导致程序员犯错了呢,很简单,机器没有报错,程序员以为是对的,所以,接下来引进一个新的函数为“断言’(assert)函数。
3.assert
assert中可以放一个表达式,表达式的结果如果为假,就报错,如果为真那就正常运行
实现代码:
#include#include//#includevoid my_strcpy(char* dest, char* src) {/*if (src == NULL || dest == NULL){return;}*/assert(src != NULL);assert(dest != NULL);while (*dest++ = *src++) {;} }int main() {char arr1[20] = "****************";char* p = NULL;my_strcpy(arr1, p);printf("%s\n", arr1);return 0;}
很明显,这个程序报错了,而且给你标注了哪里出错了,是不是很方便快捷,当然,头文件不要漏掉。
4.这阶段完整代码
这一阶段的完整代码如下:
#include#include//#includevoid my_strcpy(char* dest, char* src){assert(dest && src);//断言指针的有效性while (*dest++ = *src++){;}}int main(){//strcpy - 字符串拷贝//char arr1[20] = "xxxxxxxxxxx";//char arr2[] = "hello";//my_strcpy(arr1, arr2);//printf("%s\n", arr1);char arr3[20] = {0};char* p = NULL;my_strcpy(arr3, p);return 0;}
三、返回值
大家如果细心看那张strcpy的图,会发现两个小问题,这strcpy是有返回值的呀,还有那个const怎么一直没有解决呢?接下来,我们开始解决问题!
1.返回类型
那接下来修改一下这个代码吧!
#include#include//#includechar* my_strcpy(char* dest, char* src){assert(dest && src);char* ret = dest;while (*dest++ = *src++){;}return ret;}int main(){char arr1[20] = "*************";char arr2[] = "hello";printf("%s\n", my_strcpy(arr1, arr2));//链式访问return 0;}
这样就有返回值了!
2.const
接下来到了最激动人心的时刻,久久困扰的const该怎么做呢?下面且听我分析。
大家先来看看这张图片,生动形象的解释了const。
情况一:const 在的左边:const int p 与 int const * p 一样哦~
//const放在* 的左边,const修饰的是指针指向的内容,表示指针指向的内容,不能通过指针来改变了; 但是指针变量本身可以修改int num = 0;int n = 1000;const int* p = # *p = 20;//err p = &n;//ok
情况二:const 在*的右边:int * const p
const放在*的右边,const修饰的指针变量本身,表示指针变量本身的内容不能被修改,但是指针指向的内容,可以通过指针来改变。int* const p = #*p = 20;//ok p = &n;//err
到这里就完美解决了strcpy函数的问题。
四、完整代码
#include#include//#includechar* my_strcpy(char* dest, const char* src){assert(dest && src);char* ret = dest;while (*dest++ = *src++){;}return ret;}int main(){char arr1[20] = "*************";char arr2[] = "hello";printf("%s\n", my_strcpy(arr1, arr2));//链式访问return 0;}
总结
模拟strcpy函数让我们大家深刻理解了这个函数的原理以及用法,最好的一点是让我们了解了assert和const的使用,一举三得!!!!
客官都阅读到这边了,码字不易,求个三连支持!