前言:Hello!大家好,我是@每天都要敲代码;上一讲对于strlen库函数的使用和三种模拟实现方法相信大家都很熟悉了,strlen库函数是用来求字符串的长度,遇到'\0'终止;所需头文件是<string.h>;如果还没掌握的小伙伴可以重新复习一下:strlen库函数的使用和模拟实现<传送门>一下。这一期,我们来一起学习一下strcpy和strncpy的使用以及strcpy的模拟实现!!!
1.strcpy的使用:
对于strcpy的使用相信大家都很熟悉了, strcpy是长度不受限制的字符串函数;参数只有两个,strcpy(dest,src);意思是把src里面得内容拷贝到dest里面,下面我们直接上代码:
上面代码就是把arr2数组里的内容拷贝到arr1里面,并且我们给arr1数组足够的大小,确保arr2数组里的的内容能全部拷贝过来;我们打印arr1数组里面的数据,运行结果如下 :
2.strncpy的使用:
对于strncpy的使用大家可能就很少见了; strncpy是长度受限制的字符串函数;参数只有三个,strcpy(dest,src,n);意思是把src里面得前n个字节的数据内容拷贝到dest里面,下面我们直接上代码:
上面代码就是把arr2数组里的前4个字节的内容拷贝到arr1里面,并且我们给arr1数组足够的大小,确保arr2数组里的的内容能拷贝过来;同时我们也可以自己拷贝自己;我们打印arr1数组里面的数据,运行结果如下 :
3.strcpy的模拟实现
方法1:
解析:
我们来解析一下这个代码:
1.首先对于指针src我们加上了const,为什么呢?因为我们只是拷贝src指针里面的内容到dest,并不改变它,所以我们加上const修饰就更加的安全。
2.之后我们需要assert断言一下。
3.核心代码就需要我们思考一下,其实它和strlen的模拟实现很像,都是字符串嘛!我们还是找src字符串的\0,找不到就一直把src里面的内容赋值给dest就可以啦!
4.那么循环外面怎么又有一个*dest = *src呢?当然是把src里面的\0也拷贝进去啦!
当然,注释掉的三句代码,也可以用下面一句代码代替,他们本质上是一样的!!!
方法2:
解析:
第二种方法实际上是第一种方法的优化,方法1我们还要单独把\0拿出来进行拷贝,那我们能不能在循环内部就完成所有的拷贝呢?当然是可以的,我们直接把循环条件改一下,*dest++ = *src++,在src遇到\0之前都是赋值操作,直到src遇到\0以后,相当于*dest++ = \0;咦,这不就是循环跳出来的条件,while循环遇到0就结束循环啊!所以此时不仅能刚好跳出循环,还能把\0也能赋值过去。最终我们循环里的内容什么都不需要执行,直接 “;” 就行啦!
方法3:
解析:
为了让代码更加的优化,我们不妨用MSDN去搜索一下strcpy函数的使用:
char *strcpy( char *dest, const char *src );这好像和我们模拟实现的不太一样啊,我们模拟用的是void没有返回值,这里却用的确实char*返回的是一个char类型的指针;所以我们不妨在思考一下:在定义一个指针(暂定为start),指向dest的首地址,记住它的起始位置,在dest++的过程中,start确不会变,指针指向首元素的地址,到时候返回start这个指针不就好了嘛!!!最终的打印也会根据起始地址start打印,遇到\0终止。
每日一题:
今天给兄弟们补充一道因为越界访问造成的死循环;我们一起看一下下面代码运算的结果:
解析:
首先是肯定越界访问了,但是死循环是怎么来的呢? 先创建的i变量,优先使用高地址;之后创建数组,数组是从低地址到高地址;当我们越界访问时,就有可能使得越界访问的数组与变量i的地址相同;我们又定义arr[i]=0;当arr[12]=0,最终也会使得变量i的值增加着增加着也变成0;最终造成死循环,我们通过调试发现在i=12时,i又立刻又变成0了;我们不妨打印一下这两个地址看一下:
发现他们的地址确实是相同的!!!如果你还不懂我们不妨画个图来理解一下,下图是先创建i,在创建数组arr:
如果我们先创建数组,在创建i呢?这又是什么情况,这种就不会造成循环,只有越界访问,如下图:
以上就是strcpy和strncpy库函数的使用和strcpy函数的模拟实现,希望对你们有所帮助,有错误欢迎指出来,让我进步!!!