试想一下,如果你去一家公司面试,面试官叫你手动写一个my_strcpy函数,用于实现strcpy的功能。
你会写出什么样的代码呢?
一、初始
以下代码可以实现strcpy的作用
#include<stdio.h>
void my_strcpy(char* dest,char * src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
}
int main()
{
char arr1[] = "abcde";
char arr2[10] = { 0 };
my_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
因为循环到*src == '\0’时就截止了,没有进行下面的*dest = *src;所以\0没有被传到arr2中。而strcpy函数本身的作用还包括把arr1末尾的\0拷贝到arr2中去,所以在while循环外面,我们还要再加一句*dest = *src;用来拷贝\0
上面代码,如果满分,面试官可能只会打6、7分
二、简化
我们对上方函数代码经行简化,得到如下
void my_strcpy(char* dest,char * src)
{
while (*src != '\0')
{
*dest++ = *src++;
}
*dest = *src;
}
虽然++的优先级比*更高,但++的效果是后产生的,所以对于*dest++来说,dest++的值是原来dest的值,*拿到的是原来dest指向的字符,然后后置++的作用才产生
三、简化
不过我们还可以进行再一步简化
void my_strcpy(char* dest,char * src)
{
while (*dest++ = *src++)
{
;
}
}
来解释一下
这行代码
while (*dest++ = *src++)
依次把arr1中的a b c d e放入arr2中
当把\0放入arr2中时,while (*dest++ = *src++)中的表达式的结果就是\0,而\0的ASCII码值就是0,此时while(0),循环停止,即以\0作为结束标志,而同时\0也是被传到arr2中来了的。
可以看到,这个代码非常的妙啊,一行代码实现了两个目的,即1.拷贝字符;2.遇到\0循环停止。
四、优化
但还有一种情况,万一my_strcpy(arr2, arr1);中的arr1传入的是空指针NULL,那*src解引用时整个代码就可能发生奔溃,那么我们就需要对其进行优化。
指针在引用时最好对其进行判断,可以加上以下代码
if (src == NULL || dest == NULL)
{
return;
}
在解引用前用来判断指针是否为空。
但这个每次判断一下还是会浪费时间,
那么我们引入
assert();//断言
这个宏用于判断一个表达式,如果结果为假,输出诊断消息并终止程序。
头文件需要添加#include <assert.h>
#include <assert.h>
void my_strcpy(char* dest,const char * src)
{
assert(src && dest);
while (*dest++ = *src++)
{
;
}
}
当传入空指针,就会如下图提醒并终止程序。
当然,还会遇到一种情况,虽说很小很小概率,但我们还是可以想办法杜绝。这个情况就是我们可能把这句while (*dest++ = *src++)写成了while ( *src++=*dest++),这样就可能导致原来的字符串被改。
为了防止这样的事情发生,我们传入时可以在*src前面加一个const,这样,*src(即arr1)就不能被改了。
即
void my_strcpy(char* dest, const char* src)
整段代码优化下来就是这样
#include<stdio.h>
#include<assert.h>
void my_strcpy(char* dest, const char* src)
{
assert(src != NULL);
assert(dest != NULL);
while (*dest++ = *src++)
{
;
}
}
int main()
{
char arr1[] = "abcde";
char arr2[10] = { 0 };
my_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
这时候面试官要是看到你这样写,相信会直呼“嗯,不错不错”
简单回顾一下const修饰指针的作用
以下我们再来简单回顾一下const修饰指针的作用
const 修饰指针
const 放在*的左边 修饰的是指针指向的内容(*p),指针指向的内容,不能通过指针来改变了 但是指针变量本身是可以改变的
const 放在*的右边 修饰的是指针变量本身§,指针变量本身(p)不能修改了 但是指针指向的内容(*p)可以修改
//int main()
//{
// const int num = 10;//num是常变量
// const int* p = #
// //*(p + 1) = 0;//
//
// //num = 20; //err
//
// //const 修饰指针
// //const 放在*的左边
// //修饰的是指针指向的内容(*p),指针指向的内容,不能通过指针来改变了
// //但是指针变量本身是可以改变的
// //int n = 100;
// //const int* p = # //int const* p = #
// //*p = 20;//err
// //p = &n;
// //printf("%d\n", num);
//
// //const 放在*的右边
// //修饰的是指针变量本身(p),指针变量本身(p)不能修改了
// //但是指针指向的内容(*p)可以修改
// //
// //int n = 100;
// //int* const p = #
// //*p = 20;//ok
// //p = &n;//err
//
// //printf("%d\n", num);
// return 0;
}
如果对你有帮助,别忘了点赞👍+收藏 欢迎大家的指导 我的主页还有其他内容,关注?我,我们一起学习一起成长!
|