首先我们先简单的使用函数来模拟完成一个strcpy函数。
#include <stdio.h>
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = { 0 };
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
结果如下:
以上是我们简单用函数实现的strcpy函数,但是他函数处的代码有点嗦,我们可以对其简化:
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
}
我们可以修改成:
void my_strcpy(char* dest, char* src)
{
while (*dest++ = *src++)
;
}
*dest++ = *src++;可以理解为,先将*src中的值赋值给*dest,复制完成后,再dest++,src++,指针指向下一字符。
简化完成后,我们开始介绍const的作用,const关键字我们知道他有修饰常变量的作用,被修饰的变量成为常变量后,具有了部分常量的性质,其中之一就是:值不能被修改。
在官方给定的strcpy函数的定义如下:
定义中说明:strcpy函数把源字符串结束标志\0也会拷贝到目的地字符串中。
定义中在char* src的前面加了个const,作用是修饰这个*src,不让这个*src的值被修改。
#include <stdio.h>
void my_strcpy(char* dest, const char* src)
{
while (*dest++ = *src++)
;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[10] = "";
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
运行结果如下:
若这时的*dest++ = *src++,更改为*src++ = *dest++的话,程序执行时就会提示报错。
如:
小提示:const所在位置的不同,导致的结果也是不同的。
const修饰指针:
const放在*的左边(const char* src)
const修饰的是*p,表示p指向的对象不能通过p来改变,但是p变量中的地址是可以改变的。
const放在*的右边(const char* const src)
const修饰的是p,表示p的内容不能被改变,但是p指向的对象是可以通过p来改变的。
我们在设想一下,如果我们的arr1或arr2两个字符串中有一个被置为NULL,但是我们还硬要执行的话,这时就会出现报错,且如果是一个大型工程的话,代码量很多我们查找起来也是比较麻烦。
所以我们可以借助一个宏assert(断言),注意assert是一个宏,不是一个函数。assert()宏接受一个整形表达式参数。如果表达式的值为假,assert()宏就会调用_assert函数在标准错误流中打印一条错误信息,并调用abort()(abort()函数的原型在stdlib.h头文件中)函数终止程序。
使用assert宏需要声明一个头文件:include <assert.h>
假设我们的程序是这样:
#include <stdio.h>
#include <assert.h>
void my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
while (*dest++ = *src++)
;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[10] = "";
char* p = NULL;
my_strcpy(p, arr1);
printf("%s\n", arr2);
return 0;
}
运行结果如下:
错误信息的结尾告诉了我们assert断言程序的位置,在122行,发现实参dest为空指针了,这时,我们在回头去找函数传参的位置,发现实参一个是p一个是arr1,在往上看,就能发现arr1非空,而p是个空指针,这就排查出问题了。
所以通常我们把传递过来的参数都加上assert断言,这样如果有问题,就可以及时发现。
最后一点,定义中的函数是有返回值的为:char*。返回值是char*的原因是,这样可以实现链式访问。
如:
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
while (*dest++ = *src++)
;
return ret;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[10] = "";
printf("%s\n", my_strcpy(arr2, arr1));
return 0;
}
函数的结果直接作为printf函数的参数进行输出。结果如下:
如果我们照猫画虎写一个strlen函数该怎么写呢?
代码如下:
#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
assert(str != NULL);
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[10] = "abcdefg";
printf("%d\n",my_strlen(arr));
return 0;
}
运行结果如下: