0

strstr的模拟实现

 1 year ago
source link: https://blog.51cto.com/u_15423682/6113397
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

这是一篇介绍字符串函数strstr模拟实现的博客,包括有strstr在MSDN中的详细介绍,每一步实现的思路与方法,以及一些易错点的提醒。

一、strstr在MSDN中的注解

strstr的模拟实现_bc

寻找一个子字符串;
注解中,仅用一个简单的句子就描述了函数的作用,但这并不能让我们充分了解strstr,我们接着一步一步向下看;

1、返回值

strstr的模拟实现_字符串_02
两种情况:当string中存在Charset时,返回Charset在string第一次出现的地址;当string中不存在Charset时,返回空指针;还有一种特殊情况,当Charset指向的字符串为0长度时,返回string的地址。

strstr的模拟实现_字符串_03
  • string
    以Null结尾的,要搜索的字符串;
  • strCharset
    以Null结尾的,被搜索的字符串;

这么简单翻译,其实不好理解;说人话就是,要在字符串string中寻找字符串strCharset,而这两个字符串都必须以Null结尾,也就是说,以’\0’结尾。

strstr的模拟实现_bc_04strstr函数返回一个指向strCharset在string中首次出现的地址,函数的搜索不会包括结尾的’\0’。
到这,相信大家对strstr函数的具体作用已经大致了解,其实它就是一个字符串查找函数;

举个活灵活现的例子:
你妈叫你去仓库(这个仓库就是string)找一罐辣椒(strCharset),你找到了就告诉她在哪里(返回一个指针,这个指针指向string中的一个位置,这个位置就是strCharset第一次出现的位置),没找到就说没有(返回空指针)。

二、strstr的模拟实现

举个小例子

strstr的模拟实现_搜索_05

string字符串为acabcde,strCharset字符串为abcd,二者都以‘ \0’结尾;

string与strCharset分别用str1与str2接收;str1先后移寻找是否与str2相同,相同时两个指针再同步后移,直到str2指向’\0’时,说明已经寻找完成;

2、返回值

由于str1与str2在寻找时都已同步后移,所以我们定义一个新的指针cur(occur的结尾缩写),用来记录str1与str2相同时的位置,用以返回;

3、多次比较

  • 第二次比较时,由于str2已经后移,所以不知道strCharset的起始位置,而每次比较时,需从strCharset的起始位置开始,所以需定义一个指针,指向它;
  • 又,在传址时,str2就是strCharset的起始地址,故定义一个新指针s2专门用于寻找;

实现如下:

//模拟实现strstr
//在str1中寻找str2,若存在则返回首次出现的地址,不存在返回NULL;
char* my_strstr(const char* str1, const char* str2)
{
	//断言:str1 和 str2 指向的地址不可为空
	assert(*str1 && *str2);
	const char* s1 = str1, * s2 = str2;//寻找相同的字符
	const char* cur = str1;//记录相同字符串出现时,str1中的首地址;
	//cur 不为'\0'则往后寻找
	while (*cur)
	{
		//s1指向下一个查找的位置
		//s2指向str2,也就是strCharset的起始位置
		s1 = cur;
		s2 = str2;
		//s1,s2指向的地址不为空且相同则开始寻找
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0'	)
			return cur;
		cur++;
	}
	return NULL;
}

三、优化点与易错点

1、由于查找不会更改字符,故在定义指针与传参时,增加const,以提高代码的健壮性;
2、使用断言,确保查找的字符串不为空;
3、在判断查找完成时,不可想当然用(*s1 == *s2)进行判断,因为此时s1与s2都已后移,二者指向位置的字符并不是最后结束的字符,查找结束的标志,应该是s2指向’\0’。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK