学习很苦,结果很酷
❤️ 温馨提示:
各位童鞋们在内卷的的道路上千万要注意身体,不要一整天的坐在电脑前,多运动运动。
目录
一、用库函数strcpy实现字符串拷贝
二、自定义my_strcpy实现字符串拷贝
三、my_strcpy拷贝字符串优化版
⌛1.第一种
☎️ 2.第二种
四、my_strcpy拷贝字符串深度优化
⚽ 1.使用assert()断言
⚾️2.添加const
✏️3.const修饰指针
✒️ 4.凉皮男孩上线
一、用库函数strcpy实现字符串拷贝
#include#includeint main(){char arr1[20] = "xxxxxxxxxxxxxxxx";char arr2[20] = "hello";strcpy(arr1, arr2);//arr1目标空间起始地址,arr2源空间起始地址printf("%s\n", arr1);return 0;}
当前代码打印hello就结束了,因为strcpy函数不仅把hello拷贝过去了,连同后面的\0也一同拷贝过去了,字符串结束标志是\0,也就只会打印出hello了。
二、自定义my_strcpy实现字符串拷贝
数组名是首元素的地址,也就是char的地址
用my_strcpy将src指向的内容拷贝到dest所指向的空间
当把h拷贝过去后,要拷贝其他的内容就要使dest和src指向下一个内容
#include#includevoid my_strcpy(char* dest, char* src)//dest表示目的地,src表示源头{while (*src != '\0'){*dest = *src;dest++;src++;}*dest = *src;}int main(){char arr1[20] = "xxxxxxxxxxxxxxxx";char arr2[20] = "hello";my_strcpy(arr1, arr2);//arr1目标空间起始地址,arr2源空间起始地址printf("%s\n", arr1);return 0;}
对于指针有不理解的,可以去看我往期的文章
【明解C语言】之指针初阶详解_马桶上看算法的博客-CSDN博客C语言初阶、初阶指针、编程语言https://blog.csdn.net/m0_63033419/article/details/124002865
三、my_strcpy拷贝字符串优化版
⌛1.第一种
*dest++ = *src++是hello的拷贝
*dest= *src是\0的拷贝
☎️ 2.第二种
先将h赋给*dest,h的ASCII值不等于0。后面分别将e、l、l、o赋给*dest,它们的ASCII值均不等于0,但将\0赋给*dest的时候,\0的ASCII值是0,表达式为假,所以循环结束了。
四、my_strcpy拷贝字符串深度优化
⚽ 1.使用assert()断言
如果arr1或者arr2是空指针(NULL),就意味着dest或者src哪里都没有指向,这时如果再解引用就会出问题。
解决办法:assert()//断言
我们的程序应该有能力检查arr1和arr2是不是一个空指针,如果是就提示,如果不是就运行。assert()和if()非常类似,只不过assert()圆括号里的表达式为真,就什么事都不发生,为假,就提示错误。
例如:
assert(src != NULL)
另外assert的使用要引头文件
#include
⚠️
注意:assert()为真就什么都不发生,而为假就提示错误,这和if语句刚好相反,使用的时候注意别搞混淆了。
#include#include#includevoid my_strcpy(char* dest, char* src)//dest表示目的地,src表示源头{assert(src != NULL);//断言while (*dest++ = *src++){}}int main(){char arr1[20] = "xxxxxxxxxxxxxxxx";char arr2[20] = "hello";my_strcpy(arr1, NULL);//arr1目标空间起始地址,arr2源空间起始地址printf("%s\n", arr1);return 0;}
arr1和arr2都有可能是NULL,所以要对两个都进行断言
代码如下:
#include#include#includevoid my_strcpy(char* dest, char* src)//dest表示目的地,src表示源头{assert(dest != NULL);//断言destassert(src != NULL);//断言srcwhile (*dest++ = *src++){}}int main(){char arr1[20] = "xxxxxxxxxxxxxxxx";char arr2[20] = "hello";my_strcpy(arr1, arr2);//arr1目标空间起始地址,arr2源空间起始地址printf("%s\n", arr1);return 0;}
⚾️2.添加const
如果将源空间起始地址和目标空间起始地址弄反了,写成了*src++ = *dest++,字符串拷贝考反了,将arr1中的字符串(一堆x)拷贝到arr2中去,程序就会崩溃,因为arr2放不下arr1的内容
当我们将源空间起始地址和目标空间起始地址弄反了,怎么能够及时的发现呢?
解决办法:const
将源空间地址前加上一个const
例如:
void my_strcpy(char* dest, const char* src)
当我们加上const之后,再去编译代码,将*dest拷贝给*src,程序就会报错;而原来就算是写反了,程序也可以跑起来,加上const之后程序连跑都跑不起来,也就不会出现运行上的错误了。
那么加上一个从const就是一个很好的保护
⚠️
注意:如果*dest和*src没有写反,即使是加了const程序也不会报错
代码如下:
#include#include#includevoid my_strcpy(char* dest, const char* src)//dest表示目的地,src表示源头{assert(dest != NULL);assert(src != NULL);//断言while (*dest++ = *src++){}}int main(){char arr1[20] = "xxxxxxxxxxxxxxxx";char arr2[] = "hello";my_strcpy(arr1, arr2);//arr1目标空间起始地址,arr2源空间起始地址printf("%s\n", arr1);return 0;}
✏️3.const修饰指针
现在要求num的值不能被改变,要在num左边加上一个const,也就是这样写:
const int num = 10;
const的作用是修饰变量,这个变量被称为常变量,具有常属性,不能被修改,但本质上还是一个变量。
当我们运行代码会发现,即使是加上了const,num的值还是被改变了。
加入const的初衷就是不能改变num的值,但现在还是改变了。虽然num被const修饰,num的值不能改变,但num又将自己的地址交给了p。通过对p解引用还是将num的值给改变了。比如我们要进入教室,正常情况下只能从门进去,但是现在门被锁住了,我们还可以从窗户进去。
我们加入const的目的非常明确,那就是使num的值不能被改变。这里通过访问地址的方式还是可以将num的值改变,看似挺巧妙的,但这不符合我们的要求。那要怎么做才能把窗户也锁上呢?
解决办法:将p的左边也加入一个const
也就是这样写:
const int* p = #
运行代码就会发现,程序会报错。在这里也就相当于是把窗户也锁住了。
代码如下:
#includeint main(){const int num = 10;const int* p = #//const修饰指针的时候//const如果放在*的左边,修饰的是*p,表示指针指向的内容,是不能通过指针改变的*p = 20;printf("%d\n", num);return 0;}
⚠️
注意:虽然const修饰的是*p,但是对我的指针变量p没有影响
#includeint main(){const int num = 10;const int* p = #//const修饰指针的时候//const如果放在*的左边,修饰的是*p,表示指针指向的内容,是不能通过指针改变的//*p = 20;//但是指针变量本身是可以修改的int n = 100;p = &n;//修改了p变量本身printf("%d\n", num);return 0;}
当前代码运行结果为: 10
✒️ 4.凉皮男孩上线
以上的情况是const放在*左边,下面来介绍const放在*右边。
⛳ 比如说现在有一个女孩和男孩1,他们是男女朋友关系。男孩有十块钱,女孩想吃凉皮了,让男孩给她买凉皮,而一碗凉皮要十块钱,这个时候发生的动作是*p = 0,就是相当于男孩把十块钱花掉了。
⛳ 其实这个男孩很抠,他在想我只有十块钱,请你吃了,我就没钱了,那我才不要请你吃。于是他想了一个办法,就是在*的左边加上一个const。修饰*p,这个时候*p = 0这个动作就不能完成了。
⛳女孩生气了,十块钱你都舍不得,我看男孩2也挺帅的,分手吧!我去作男孩2的女朋友了。这个时候发生的动作是p = &n。
⛳ 这个时候男孩1慌了,你要跟我分手,那那那那那不行,于是男孩叕想到了一个办法,那就是在*的右边加上const。
⛳有一天,男孩想到了一个坏主意。那就是将*的两边都加上const