我们都知道strstr函数是常见的字符函数,主要用于查找字符串中是否有目标字符串,若有就返回字符串字开始的地址。

下面是关于strstr函数的定义:

模拟实现strstr库函数(指针回退问题)_#define

模拟实现strstr库函数(指针回退问题)_字符串_02编辑

知道了大概用法之后,我们今天要模拟实现strstr函数 ,我们将从下面几点入手

1.画图直观理解strstr函数的操作方式

已知“bcd”是要在“abbbbcdef”中查找的字符串,如下图:

模拟实现strstr库函数(指针回退问题)_#define_03

模拟实现strstr库函数(指针回退问题)_#define_04编辑

结果应该返回的是第四个“b‘的地址 

模拟实现strstr库函数(指针回退问题)_#define_05

模拟实现strstr库函数(指针回退问题)_#define_06编辑

可具体需要我们如何去寻找该地址呢??

下面我们继续画图演示:

1.首先设置两个指针p1和p2,分别指向连个字符串的首元素 

模拟实现strstr库函数(指针回退问题)_字符串_07

模拟实现strstr库函数(指针回退问题)_#define_08编辑

2.之后解引用p1和p2,目的是为了比较两元素是否相等,若不相等,则p1继续往后移动,直至p1解引用的元素与p2中解引用的元素相同,如下图:

此时p1中的元素与p2中元素相同,则p2此刻需要向后移动以检验后面的几个元素是否相同

模拟实现strstr库函数(指针回退问题)_bc_09

模拟实现strstr库函数(指针回退问题)_字符串_10编辑

3.因为刚才第一个元素相同,所以现在同时移动p1和p2检验后面的元素是否相同

结果发现不同,此时p1需要返回刚刚往后的地址的后一个地址处即返回第2个b处p2也需要返回先前的地址即b的地址处,这就是指针的回退 

模拟实现strstr库函数(指针回退问题)_bc_11

模拟实现strstr库函数(指针回退问题)_字符串_12编辑 回退后:

模拟实现strstr库函数(指针回退问题)_bc_13

模拟实现strstr库函数(指针回退问题)_#define_14编辑

通过观察我们可以知道,本函数的模拟需要不断重复指针的回退,因为我们不一定一次性找到目标的地址,所以为了避免忘记先前的地址,我们需要再次创建新的指针来记住原先的位置 

在第三步中指针p2到了”c“的位置,但我们发现这个位置需要退回,所以我们要将第二个字符串的地址记录在新的指针s2中,同理需要将p1退回的地址记为s1保存(此时s1与p1是相同的)

这里要重点体会以下指针的退回哦!!

模拟实现strstr库函数(指针回退问题)_bc_15

模拟实现strstr库函数(指针回退问题)_bc_16编辑

之后继续进行以上三步的操作即可。

那么程序何时停止??

1.当第二个字符串访问到最后一个’\0‘字符,就是找到了

2.当第一个字符串访问到最后一个’\0‘字符,这里有可能找到也有可能没有找到,找到了是因为它与第二个字符串刚好同时访问到了’\0‘,没有找到是因为第一个字符串的数据已经访问完了。

下面是具体的模拟实现代码:

#define _CRT_SECURE_NO_WARNINGS1
#include<stdio.h>
char* my_strstr(char* cp, char* p2)
{
	char* p1 = cp;
	char* s2 = p2;
	char* s1 = p1;
	while(*s1)
	{
		p1 = s1;
		p2 = s2;
		while (*p1 && *p2 && *p1 == *p2)
		{
			p1++;
			p2++;
		}//这是当第一个字符相等后判断后面的字符是否相同的循环
		if (*p2 == '\0')
		{
			return  s1;
		}
		s1++;
	}
	return NULL;

}

int main()
{
	char arr1[] = { "abbbbcdef" };
	char arr2[] = { "bcd" };
	char* p1 = my_strstr(arr1, arr2);
	printf("%s", my_strstr(arr1, arr2));

	return 0;
}

模拟实现strstr库函数(指针回退问题)_bc_17

谢谢观看,欢迎批评指正