一、前言
strcpy函数是string.h中的库函数,功能是传入两个字符数组str1,str2,把str2复制到str1上。在这里我们使用自定义函数去实现strcpy函数。因为我们标题上面也写了是实现高级的strcpy函数,一般方法的思路以及步骤很简单,在这里就不多去阐述。
二、实现
1、一般写法
void my_strcpy(char* str1, char* str2)
{
while (*str2 != '\0')
{
*str1 = *str2;
str1++;
str2++;
}
}
一般我们去自定义函数去实现strcpy函数就是这样的内容
2、进阶写法
char* my_strcpy(char* str1,char* str2)
{
while (*str1++ = *str2++)
{
}
}
在这里注意while循环条件中的是 = 而不是 == 也就是说我们在这里使用的是赋值而并非判断相等,而后置的++可以在*str1=*str2的步骤后进行类似于一般步骤中str1++;str2++;当str2字符串结尾时也就是把‘\0’赋值给str1时括号内的语句判断为false。刚好此时字符串的复制结束,循环结束。
所以说只用写一行代码就可以实现了,假如在面试中面试官刚好出到这个题,这样的写法可以让他眼前一亮。
———————————— 我是分割线 ————————————————
。。。but。。。所谓眼前一亮也就是一亮了,下面的写法是可以亮瞎他的眼。
进阶写法中还是有一些不足的:
1、如果传入的是一个空指针的话,程序就不能达到目的。
2、如果在写入的时候复制的顺序写反,不太容易查找出来,不利于我们去找bug
3、上面的两种写法我们使用void定义的函数,如果主函数需要返回指针的时候,使用char*定义的函数经过++后的str1指向的其实是字符串的最末端,使用返回的指针去打印的时候不能打印出复制后的字符串。
3、高级写法
#include<assert.h>
char* my_strcpy(char* str1, const char* str2)
{
assert(str1 != NULL);//断言
assert(str2 != NULL);
char* p1 = str1;//此函数到结束时str1指针指向的是字符串结尾,所以定义p1代替str1返回。
while (*str1++ = *str2++)
{
}
return p1;
}
1、assert的作用是断言。assert(str1 != NULL)的作用是断言str1不能等于NULL。这样在str1为空指针的时候编译器可以及时报错(编译错误),而不是在运行中再去找错(运行中错误)。
2、使用const char* str2 就可以避免因为赋值顺序写错而导致的运行中错误,可以在编译阶段直接报错,这个const修饰指针变量的方法还是比较麻烦的,可以看我下一篇文章详细解读。
3、我们定义一个新的指针变量,把未移位之前的指针放进去,返回这个指针就可以解决str1指向的是字符串的最末端这个问题。
三、总结
这个由一般到高级的过程,由繁到简,再由简到繁。
这里我们高级写法中不能避免出错,毕竟人为打的代码不能保证没有错误吗,但是能保证当你出错时能够很容易的找出来,也就是由运行中错误转化为编译错误,在编译器上就可以直接报出来,而不用在调试去找这个错误。
这是一个非常良好的代码风格,这在以后到公司去写一些大工程几万行代码的那种的时候,会有效地避免工程出错,而且,在面试的时候也会让面试官对你刮目相看。