通过模拟strcpy函数学习编程思想

Posted 东条希尔薇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过模拟strcpy函数学习编程思想相关的知识,希望对你有一定的参考价值。

目录

strcpy函数简介

最初版代码

第一次优化:简化代码

第二次优化:代码有效性

断言(assert)的介绍

代码实现

第三次优化:字符串的安全性

关于const修饰符

代码实现

第四次优化:靠近标准库函数

总结与提示


​​​​​​​

strcpy函数简介

strcpy是c语言库中的一个函数,需要包含<string.h>头文件。它可以实现数组的拷贝。将src数组中的所有元素(包括末尾的\\0)拷贝在另一个dst数组中。

以下是cplusplus网站中对strcpy函数的介绍

 我们通过介绍,可以先尝试自己模拟strcpy的实现

最初版代码

我们需要传进两个常量字符串在这个函数中,然后对每个字符进行操作

void my_strcpy(char* dst,char* src)
{
	while(*src!='\\0')//检测到字符串终止后结束复制
	{


		*dst = *src;//这里是复制操作
		dst++;//每复制一个字符后,复制下一个字符
		src++;
	}
	*dst = *src;//放置\\0
}

复制出来后的dst数组就应该为以下的输出结果

 但这个函数,虽说确实可以完成复制的功能,但是仍然存在大量的问题,也不够简洁。

以下几步会对代码进行逐步优化。

第一次优化:简化代码

我们可以直接将代码这样放置

void my_strcpy(char* dst, char* src)
{
	while (*src != '\\0')
	{
		*dst++ = *src++;//简化

	}
	*dst = *src;//放置\\0
}

代码中的++运算符是后置的,可以做到先使用此次的变量,也就是先替换增加之前的字符,再进行++操作,找到下一个字符。

也可以进一步简化

void my_strcpy(char* dst, char* src)
{
	while (*dst++ = *src++)//表达式的结果为dst的字符,'\\0'ASC值为0,自动停止
	{
		;
	}
}

这样的优化,不仅继承了前一段代码的优点,也少了替换'\\0'的一步

在while循环中,先把src替换到dst变量中,再判断dst是不是为0。

如果src已经遍历到'\\0'了,替换到dst中,而因为'\\0'的ASCii值为0,判断为假,这个while将会终止,也将会停止复制。

经过这一次优化后,代码会变的更加简洁。

第二次优化:代码有效性

经过了第一次优化,基本实现了将代码简化的功能,但是如果在传参过程中传入了空指针,可能会导致程序出现问题

这样程序如果在后期使用中如果意外传入了空指针,将会导致程序崩溃。 

为了解决这一问题,我们可以使用断言来帮我们判断是否为空指针

断言(assert)的介绍

断言是c语言提供的一种函数,需要包含<assert.h>头文件,如果在assert里面的表达式为false,程序将会直接报错,随后退出程序

以下是使用示例

#include<assert.h>

int main()
{
	int a = 0;
	int b = 10;
    printf("hehe\\n");//验证assert前后语句会不会被执行
	assert(a>b);//显然此表达式为假
    printf("hehe\\n");
	return 0;
}

当判断到assert为假时,程序直接报错

并且会给我们提示在哪一行触发的断言 ,在断言后的语句将停止执行。

这个函数可以给我们代码的优化提供以下的提示:

我们可以使用assert断言检查传进的字符串是否是空字符串,如果是直接终止程序的运行。

这样我们就可以写出下面的代码。

代码实现

#include<assert.h>
void my_strcpy(char* dst, char* src)
{
	//if (src == NULL||dst==NULL)//防止传入空指针,保护程序
	//{
	//	return;
	//}
	/*assert(src != NULL);
	assert(dst != NULL);*///为假报错
	//assert(src);
	//assert(dst);
	assert(dst && src);
	while (*dst++ = *src++)//表达式的结果为dst的字符,'\\0'ASC值为0,自动停止
	{
		;
	}
}

 这样我们就程序有效性的优化就完成了。

第三次优化:字符串的安全性

我们在编写程序的时候,可能会出现在上面的代码中将dst和src写反位置的情况

这样将会造成src被意外修改,程序的安全性较低

也可能会有其他外界因素,造成src被意外修改

于是,我们考虑可以使用const来修饰src,防止src被意外修改

关于const修饰符

const是c语言的一种修饰符,它限定了一个变量不能被随意改变

int main()
{
	const int num = 0;
	num = 10;
	return 0;
}

 但虽然使用const修饰了,但是num的本质却仍然是变量。

那么num能不能被修改呢

你别说还真有

我们可以使用指针间接修改num

int main()
{
	const int num = 0;
	int* p = &num;
	*p = 10;
	printf("%d\\n", num);
	return 0;
}

程序不会报错,但是这种写法其实并不支持,它违背了const的初衷。


我们可以使用const的特性,修饰我们的src字符串,使其无法被修改

代码实现


#include<assert.h>
void my_strcpy(char* dst, const char* src)
{
	assert(dst && src);
	while (*dst++ = *src++)
	{
		;
	}
}

这样保证了程序的健壮性。

第四次优化:靠近标准库函数

将返回值设为char*

char* my_strcpy(char* dst, const char* src)//保护src
{
	char* ret = dst;//模拟库函数,第一个字符地址
	//if (src == NULL||dst==NULL)//防止传入空指针,保护程序
	//{
	//	return;
	//}
	/*assert(src != NULL);
	assert(dst != NULL);*///为假报错
	//assert(src);
	//assert(dst);
	assert(dst && src);
	while (*dst++ = *src++)//表达式的结果为dst的字符,'\\0'ASC值为0,自动停止
	{
		;
	}
	return ret;
}

至此,代码全部优化完毕

总结与提示

  1. 使用assert断言检查程序的通用性
  2. 使用const保护一些常量字符串,常量数据等,使程序更加健壮。
  3. 注释的重要性

本期内容到此结束啦!由于作者水平有限,文章中如有不足与疏漏之处在所难免,希望各位大佬提出你们宝贵的意见!笔芯~

以上是关于通过模拟strcpy函数学习编程思想的主要内容,如果未能解决你的问题,请参考以下文章

模拟实现strcpy函数

通过编写字符复制函数strcpy函数学编程

仰视源代码,实现strcpy

STM32模拟Linux自动初始化,秀

C语言之库函数(strlen,strcpy,strcmp)模拟实现

c语言 strcpy,strcat,strcmp函数模拟实现