自行实现strcpy,strcat,strcmp函数

本文介绍了如何在C语言中自行实现strcpy、strcat和strcmp这三个常用的字符串处理函数。在实现过程中,重点讲解了使用assert进行空指针检查的重要性,以及在实现字符串操作时对内存安全的关注。通过while循环和临时变量巧妙地实现了字符串的拷贝和比较功能。
摘要由CSDN通过智能技术生成

一、strcpy

在这里我们需要科普一个东西:断言

何为断言?如果你是字面理解,没错就是断定一句话是不是真的。简单吧?当然我们C语言的断言是以函数assert()来判断一个表达式或者一个值是否是我们需要的,此外使用这个函数需要引用一下assert.h这个头文件。assert断言的用法很简单,就是在一个表达式内判断所需的表达式要判断的值是否是我们需要的。如有以下的函数体

void My_strcat(char *src,char *desc)

{

 ......

}

上面的函数是自定义的字符串连接函数,我们要认知分析已知条件:接收进来两个指向字符类型的指针,分别是原串和要添加的串,但是我们一定要注意,接收进来的src和desc是不能为空的,至少src在这个后面要连接后面的字符串,所以它不能为空,如果为空,后面的字符串连在一个空指针后面,啥情况???,后面如果要打印连接后的字符串,是不是就发生空指针异常了?是吧。所以src不能为空,我们要如何判断它吧为空呢?回想刚刚的断言,在这个时候是不是能够用上?我们只需在进入函数体的第一时间使用assert(src!=NULL),为了确保安全,我们把desc也使用断言,来个双保险。

回到assert,num为0?assert(num!=0); p不为空指针?assert(p!=NULL)

细节不用说,assert只在条件成立的情况下才能继续执行,如果说条件不成立,那么就会在此报错,并且会暂停程序。

接着我们回来实现一下strcmp();下面是它的声明(在linux中使用 man strcpy可以看到,百度也有)

它是一个返回值为char*类型的(为什么要返回值???),接收两个字符串的函数,注意第二个参数使用了const修饰符,现在表示指向内存单元的内容不可变。当然第一个肯定是要变的。ca

我们先思考它的是如何实现字符串拷贝的,既然是字符串,那只能一个一个来,也就是src中的字符逐个复制到了dest里面,当然dest也是逐个接收的。这里你也许有点想法了,使用个for循环,dest和src逐个赋值。这样写代码有点多,这里我们使用while循环,减少代码行数。

char *My_strcpy(char *desc, const char *src)
{
	assert(desc!=NULL && src!=NULL);
	char *p = desc;
	while (*desc++ = *src++);
	return p;
}

来头就断言,保证我们的复制活动内正确的同时,也为以后访问提高安全。

我们要注意:src必须有足够的空间存储desc,想一想,如果不能,是不是多余的字符就被复制到未被分配的内存中,称为非法的内存访问。

接着我们用一个暂时性标记记住现在desc的地址,因为待会它要与src生死相依,直到同赴\0字符结束循环,最终由标记重新带回“最初的原点”,到里这个函数就结束了。再看strcat的自我实现。

二、strcat的自我实现

还是先看看strcat的声明

跟strcpy差不多,所以我们先分析思路,desc先绕到\0处,接着从src逐个复制过来

char *My_strcat(char *desc, const char *src)
{
	assert(src != NULL);
	char *p = desc;
	while (*desc++);
	desc--;
	while (*desc++=*src++);
	return p;
}

三、strcmp的自我实现

strcmp是字符串比较函数,通过逐个对比两个字符串的每个字符,遇上不相等的就返回字符间的ASCII值,又一次逐个比较,最后返回的还是字符间的ASCII值,因此,我们可以借鉴上面的思路。写出如下函数

int my_strcmp(const char *desc, const char *src)
{
	assert(src != NULL && desc != NULL);
	//desc和src相同的就后移,其中一个当前指向存贮‘\0'时,停止循环
	while (*desc++ == *src++ && *desc != '\0' && *src != '\0');
	if (*desc == '\0'&& *src == '\0'){
		return 0;
	}
	return *desc-*src ;

}

但是还是麻烦了,因为我们对于字符串的比较又返回他们之间的差值,完全可以用一个临时变量和while循环来解决嘛,于是有了下面的优化版

int My_strcmp_1(const char *str1, const char *str2)
{//
	assert(str1 != NULL && str2 != NULL);
	int tmp;//*str - *str2
	while ((tmp = *str1 - *str2) == 0);   //当某个字符串到\0后 循环退出
		return tmp;
}

是不是设计的超级简单?哈哈,这里的tmp变量和==0的条件用的非常好,tmp一旦不等于零,循环就结束,并且现在tmp的值刚刚好是差值,直接返回。这个设计思路很棒,以后大家可以借鉴借鉴,减少代码冗余。

再补充一个strlen的自我实现,strlen计算是不包含\0这个元素的。所以灵活使用这个条件。我们可以写出如下代码

int My_strlen(const char *str)
{
	int  length = 0;
	while (*str)
	{
		length++;
		str++;
	}
	return length;
}

最后给大家可以试着去实现strncpy,strncmp等等函数,它们只是对复制和比较的字符进行了限制。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值