版本1
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//dest 是指向目标空间的
//src 是指向源字符串的
//1
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;//\0
}
int main()
{
char arr1[] = "abcdef";//[a b c d e f \0]
char arr2[10] = "xxxxxxxxx";// [ ]
my_strcpy(arr2,arr1);
printf("%s\n",arr2);
return 0;
}
把两个字符串的地址传进去,进入while循环,指针解引用给目标字符串赋值,并将两个地址都加1,直到源字符串的地址指向的内容为'\0'时,就停止循环,但是这样的循环是无法将'\0'赋值到目标字符串的。所以还需要在循环的后面再赋值一次,将'\0'赋值进去。
这个版本的方法是最直白的,但不是最优的
版本2
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest++ = *src++;
}
*dest = *src;//\0
}
int main()
{
char arr1[] = "abcdef";//[a b c d e f \0]
char arr2[10] = "xxxxxxxxx";// [ ]
my_strcpy(arr2,arr1);
printf("%s\n",arr2);
return 0;
}
版本2在1的基础上,把循环中的内容改动了。*dest++ = *src++;在这个代码中,虽然操作符++的优先级比解引用操作符优先级高,但是在这个表达式中,也就是*dest++里,是后置++,要先解引用,后自增,也就完成了字符赋值的功能。
版本3
void my_strcpy(char* dest, char* src)
{
//1. 拷贝字符
//2. 遇到\0 循环停止
while (*dest++ = *src++)
{
;
}
}
int main()
{
char arr1[] = "abcdef";//[a b c d e f \0]
char arr2[10] = "xxxxxxxxx";// [ ]
my_strcpy(arr2,arr1);
printf("%s\n",arr2);
return 0;
}
这个版本中,把上个版本中while循环的内容放到了while循环的判断条件。这个表达式是有值的*dest++ = *src++,它的值是*src。所以在判断循环条件的时候,就进行了赋值,并且当*src的值为'\0'的时候,先完成赋值操作,然后表达式的值算出来为0后,停止循环。
版本4
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
//dest 是指向目标空间的
//src 是指向源字符串的
//5
char* my_strcpy(char* dest, const char* src)
{
assert(src != NULL);//断言 - release版本可以优化掉
assert(dest != NULL);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdef";//[a b c d e f \0]
char arr2[10] = "xxxxxxxxx";// [ ]
char *ret = my_strcpy(arr2, arr1);
printf("%s\n",ret);
return 0;
}
assert函数是断言函数,当assert中的条件为假时,运行结果里会自动由assert报错。这样可以避免系统报错。
总之,这个代码的2、3还是值得去学习借鉴的。特别是把表达式当成循环的条件。