赞
踩
要想自己实现strcpy函数,咱们就要先了解它功能是啥。首先我们知道它是一个复制字符串指令。
具体来说strcpy(arr2,arr1)将arr1的内容复制给arr2。ok,大致了解到这,我们先实现这一部分的内容。
实现过程是这样的:首先函数传入进去的是数组首元素地址,我用了指针接收,这个时候这个指针变量就代表了我字符串的首元素地址。接着进入循环,因为字符串“hello”,实际上是“hello\0”。我们要复制hello,那么循环条件就是找到\0为止。*arr2++ = *arr1++等价于*arr2 = *arr1;arr2++;arr1++;因为它们都是后置++,干脆把它们和在一起就变成了*arr2++ = *arr1++。这个时候就是先赋值完后一起++。最后找到\0,跳出循环,再把\0赋给arr2。
再来讲一下assert是什么,好处是什么。
assert(空间)用来代替if判断空间是否开辟成功,或者说判断是不是空指针。它和用if语句来判断空指针的好处是省事,最重要的是用assert判断出来的空指针,它会明确告诉你在哪一行犯的错误。如图:
这里就明确告诉你在16行的assert判断出了空指针,你在顺藤摸瓜就可以知道问题出在哪了。可能你会认为这用处不大,还得自己再找。我只能说已经很好了,这才几行代码,如果做大项目的时候,一运行,发现错误,你只能慢慢找。用if语句可不会让你这么好找。
做到这里其实已经实现的差不多了。但是我们可以看到在细节上还是有点差距。
这里为了方便直接比较。可以看到原本的strcpy还有个const来修饰。
const的作用是什么呢?简单来说就是限制你的改变。
这里是const char* source,意思是不让你修改score所指向的东西大小 ,但是你可以把score所指向的东西换一个。意思就是*score(解引用了这时候代表的是地址里存储的东西,在代码中是“hello”)不能改了,但是score(存储的是地址,在代码中是arr1)能改。
既然有这个区别,当然也就有char* const source,这个和上述的就相反。
总结一下:
const 修饰指针
1. const 放在*的左边, *p不能改了,也就是p指向的内容,不能通过p来改变了。但是p是可以改变的,p可以指向其他的变量
2. const 放在*的右边,限制的是p,p不能改变,但是p指向的内容*p,是可以通过p来改变的
讲到这里,我把代码改一下顺便优化一下。
先前讲过实现过程,发现过程有些重复的地方。这里改了一下。
观察这个,可以发现我把*arr2++ = *arr1++直接当成判断条件。是因为原来的函数又要找到\0,又要跳出循环的时候再赋值,我直接把这个当成表达式就可以不用跳出循环的时候再赋值了。直接再循环里面赋值,然后因为\0的ASCII码值就是0,所以判断*arr2=‘\0’的时候就跳出循环,就刚刚好。
最后我们比较一下,发现还是差了一点。
这里的strcpy是有char*类型的返回值的。有什么区别,或者是用处呢。我来展示一下。
这里要想返回值可以直接使用出来打印,我们需要注意的是:当你while循环完之后,*arr2所指向的地址已经是最后一位数了,如果这个时候你要返回arr2的话,就无法打印出来全部的arr2,这个时候只需要把一开始的arr2所指向的字符串首元素地址存储其来,到最后返回这个值,在代码中就是ret,然后printf就按照你这个首元素地址访问整个字符串。也就是链式访问了。
这样的好处是让代码更加的灵活,如果用void的话,就无法利用这个返回值。其实很多函数都有返回值,而且都很好用,就比如scanf函数实现多组输入。
讲到这里,strcpy函数已经实现的差不多了。源码奉上:
- char* my_strcpy(char* arr2, const char* arr1)
- {
- assert(arr2 && arr1);
- char* ret = arr2;//把一开始的arr2所指向的字符串首元素地址存储其来
- //把src指向的字符串拷贝到dest指向是的数组空间,包括\0字符
- while (*arr2++ = *arr1++)
- {
- ;
- }
- return ret;//最后返回这个值
- }
-
- int main()
- {
- char arr1[] = "hello world";
- char arr2[20] = { 0 };
- //链式访问
- printf("%s\n", my_strcpy(arr2, arr1));
-
- return 0;
- }

如果有什么地方讲错或者不理解的,欢迎指出,提问。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。