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

一、strstr在MSDN中的注解

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

1、返回值

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

2、参数

image.png

  • string 以Null结尾的,要搜索的字符串;
  • strCharset 以Null结尾的,被搜索的字符串;

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

3、标注

image.pngstrstr函数返回一个指向strCharset在string中首次出现的地址,函数的搜索不会包括结尾的'\0'。 到这,相信大家对strstr函数的具体作用已经大致了解,其实它就是一个字符串查找函数;   举个活灵活现的例子: 你妈叫你去仓库(这个仓库就是string)找一罐辣椒(strCharset),你找到了就告诉她在哪里(返回一个指针,这个指针指向string中的一个位置,这个位置就是strCharset第一次出现的位置),没找到就说没有(返回空指针)。

二、strstr的模拟实现

举个小例子 7476DDFC44291D9BBFF73F924A06B5C1.pngstring字符串为acabcde,strCharset字符串为abcd,二者都以‘ \0’结尾;

1、寻找

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'。