字符串比较

字符串比较之初级程序员和高级程序员

1. 问题的引入

这个话题的来源是这样的:开发过程中不可避免的用到了字符串比较的操作,按理说这个并不复杂,因为有现成的接口可以使用(strcmp, strncmp, memcmp等),我在使用过程中也没有仔细考虑过这些接口的具体区别。后来一个工作经验丰富的同事看代码调优时说到了这一点:来,看看你的代码有什么问题吗?

举个例子,我最初的代码是这样:

#include <stdio.h>
#include <string.h>

void main(void)
{
	char *str1 = "asdfghjkl";
	char *str2 = "asdfghjrtw"
	
	if(strlen(str1) == strlen(str2) && !memcmp(str1, str2, strlen(str1))){
		return 1;/*两个字符串一样,返回1;不一样返回0*/
	}else{
		return 0;
	}
}


这个代码在语法和逻辑上并未错误:

  • ①先比较字符串长度;
  • ②在比较字符串内容

在字符串长度不同的情况下,就没有比较比较字符串内容了。个人感觉这逻辑很严密,然后我的回答是:“我没有看出什么问题呀!”。

然后后面就是涨姿势的时刻了。

在这里插入图片描述

2. 出现的问题

2.1 时间复杂度

上述函数的实现时间复杂度是多少呢?
O ( n ) + O ( n ) + O ( n ) + O ( n ) = 4 ∗ O ( n ) 。 O(n) + O(n) + O(n) + O(n) = 4*O(n)。 O(n)+O(n)+O(n)+O(n)=4O(n)

  • strlen() : O(n)
  • memcmp() : O(n)

比较两个字符串,时间复杂度是4O(n),效率确实很低。

正常情况下,一次遍历便可以确定两个字符串是否相等,时间复杂度为O(n)。

2.2 string类的几个函数
  • strlen

  • strcmp

  • strncmp

  • memcmp

string类的几个函数有一个共同的特点:只操作字符串,不处理那些无法打印的字符。默认都是以’\0’作为字符串的结束(strlen不计算最后的‘\0’字符)。strlen的基本实现应为是:如果不是’\0’, 长度递增1;比较函数,它们也都需要逐个字符遍历(最终可能为bit)比较。也就是说他们都需要遍历一遍字符串才能得到结果。

memcmp函数比较的是指定的内存范围,而不管该内存地址中的内容是否为字符串、其他特殊字符。

举个例子:

#include <stdio.h>
#include <string.h>

void main(void)
{
	char str1[100] = "asdfghj";
	char *str2[100] = "asdfghj"
	
	if(memcmp(str1, str2, sizeof(str1))){
		return 1;/*两个字符串一样,返回1;不一样返回0*/
	}else{
		return 0;
	}
}

这个例子中,由于我并没有初始化str1str2,即使它们前8个字符一致,但是后续的92个字节的内存空间的内容并不知道,因此正常情况下为0,即不相等。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZ9OZscz-1601516609655)(C:%5CUsers%5CAdmin%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201001093441564.png)]

3. 怎么实现效率高呢?

#include <stdio.h>
#include <string.h>

void main(void)
{
	char *str1 = "asdfghjkl";
	char *str2 = "asdfghjrtw"
	
	if(!strcmp(str1, str2, strlen(str1)+1)){
		return 1;/*两个字符串一样,返回1;不一样返回0*/
	}else{
		return 0;
	}
}

时间复杂度降为2*O(n)。性能提高了一倍。

在这里插入图片描述

那么这个问题严重吗?

如果想进阶高级,那这是很基础并且很严重的问题了。从这个问题可以看出(我)基础水平一般,没有深入考虑过性能、效率问题。初级和高级的区别差很多吗?我们从这个问题中应该可以窥见一斑。我们往往忽略的地方,可能正是人家提高进阶的地方。以后工作工程中,应该多多思考了,在实现基本功能的前提下,考虑下程序的时空复杂度,通过对程序时空复杂度的分析,代码水平应该可以有所进步。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叨陪鲤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值