1.函数功能参数介绍
该函数的功能就是把一个字符串复制到另外的一个数组,包括'\0';
2.首先我们要明确字符串的复制也是包括最后的\0的;
void mystrcpy(char* dest, char* src) { while (*src!='\0') { *dest = *src; dest++; src++; } *dest = *src; } int main() { char arr1[] = "hello world"; char arr2[20] = "xxxxxxxxxxxxxx"; mystrcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
跳出while循环之后就会把末尾的\0实现复制;
3.继续优化----------------------------------------------
我们阅读上面的资料就会发现strcpy的返回值就是dest,所以我们利用这个就可以继续优化代码,
让自定义函数返回dest,因为循环的过程中dest发生了变化所以我们定义一个新的指针变量记录dest
的初始位置,并且作为返回值;
char* mystrcpy(char* dest, char* src) { char* ret = dest; while (*src != '\0') { *dest = *src; dest++; src++; } *dest = *src; return ret; } int main() { char arr1[] = "hello world"; char arr2[20] = "xxxxxxxxxxxxxx"; printf("%s\n", mystrcpy(arr2, arr1)); return 0; }
4.代码继续优化
像这样,如果有空指针,我们可以使用assert断言,这样就可以准确的找出程序的出错位置,如果没有断言,我们就无法知道自己错在哪里,但是断言会准确的告诉我们出错的位置,提高代码的可读性,但是记住需要包含assert.h的头文件;
#include<assert.h> char* mystrcpy(char* dest, char* src) { char* ret = dest; assert(dest != NULL); assert(src != NULL); while (*src != '\0') { *dest = *src; dest++; src++; } *dest = *src; return ret; } int main() { char arr1[] = "hello world"; char arr2[20] = "xxxxxxxxxxxxxx"; char* p = NULL; mystrcpy(p, arr1); printf("%s\n", arr2); return 0; }
5.继续优化
#include<assert.h> char* mystrcpy(char* dest, char* src) { char* ret = dest; assert(dest != NULL); assert(src != NULL); while (*dest++ = *src++)//到\0的时候就会结束,因为\0的ascii是0 { ;//空语句 } return ret; } int main() { char arr1[] = "hello world"; char arr2[20] = "xxxxxxxxxxxxxx"; char* p = mystrcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
这里面让while循环语句里面的内容变得更加精炼,把其实现的部分放到了判断条件里面;
解引用操作符不会作用于加加,这样指针继续向后移动,当到\0的时候,控制循环条件的赋值语句的结果是\0的ASCII值,也就是0,这样就结束了循环;
6.到这里,函数的功能就已经实现了,但是会发现少了参数里的const,补上就好了,其实const的作用就是让我们无法改变修饰的值;
char* mystrcpy(char* dest, const char* src) { char* ret = dest; assert(dest != NULL); assert(src != NULL); while (*src != '\0') { *dest = *src; dest++; src++; } *dest = *src; return ret; } int main() { char arr1[] = "hello world"; char arr2[20] = "xxxxxxxxxxxxxx"; char* p = NULL; mystrcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
7.const修饰指针变量
(1)当const放在*左边的时候,指针指向的内容不能改变,指针本身可以改变;
(2)当const放在*右边的时候,指针本身不可以改变,但是指向的内容可以改变;
(3)当*的左右都有const,无论是指针本身还是指向的内容,都无法改变;
8.明白const的作用,再回到函数的功能实现,就会发现const的必要性,如果在过程里面,我们把*src和*dest的位置颠倒了,程序就会报错,因为这样改变了*src,加上const可以让我们的程序变得更加严谨。
9.利用const,assert我们实现strlen的功能
#include<assert.h> size_t mystrlen(const char* p) { assert(p != NULL); char* left = p; size_t count = 0; while (*p) { p++; count++; } return count; } int main() { char arr[] = "wj djekd kedkkk"; size_t len = mystrlen(arr); printf("%zd\n", len); //%u打印无符号数的,和%zd差别不大; return 0; }
资料显示,strlen的返回类型是size_t,这个是位sizeof设计的一个类型,是unsigned int 或者是
unsigned long类型,所以我们把len,count都设计为size_t类型。