库函数strstr介绍
char * strstr ( const char * str1, const char * str2);函数返回字符串str2在字符串str1中第⼀次出现的位置头文件strting.h
- 用法:
#include <string.h> #include <stdio.h> int main() { char str1[] = "abcdefg"; char str2[] = "cde"; char* ret = strstr(str1, str2); printf("%s", ret); return 0; }
- 输出结果:
实现思路
函数的返回值类型和参数
char* my_strstr(const char* str1,const char* str2); //返回的是字符串地址,用char* //参数str1和str2分别接收目标字符串和源字符串的地址 //我们仅仅希望这个函数的功能是返回字符串str2在字符串str1出现的位置, //不希望他能改变字符串,加上const使它变得更安全
(代码1)
目标字符串和源字符串
char str1[] = "abcdcdefg"; char str2[] = "cde";
(代码2)
在my_strstr函数内,str1和str2接收了它们的首地址
(图1)
再通过指针偏移来一一对比*str1和*str2是否相同,如果*str1不等于*str2的话,str1会一直往后偏移,直到遇到“\0”。
但是现在出现了一个问题比如我们的两个字符串查到了这个地步:
(图2)
目标字符串就要从第二个字符串重新开始,而str2要回到起始位置,为了方便回起始位置了,所以我们就让str1和str2指向首地址,不要动,再重新创建新指针。
s1和s2代替了以前str1和str2的作用,cur的作用是指向下一次在目标字符串中比较源字符串的位置,刚开始让它们都指向首地址。
char* cur = str1; char* s1 = str1; char* s2 = str2;
(代码3)
(图3)
现在我们假设再查到图2的地步:
此时,目标字符串是从cur指针的位置开始往后查,发现前面两个字符相等,但是第三个字符不相等,所以,cur要向后偏移一位,从下标3开始查,而s2要回到起始位置str2。这样反复循环,循环的条件是*cur!=0,如果*cur=0了说明目标字符串找不到源字符串。代码如下:
while (*cur) { if (*s1 != *s2) { cur++; s1 = cur; s2 = (char*)str2;//因为str2是const char*类型, //为了防止编译器报警告,把str2强制装换成和s2一样的类型 }
(代码4)
在代码4的循环内,还要加个循环就是*s1和*s2相等的情况,*s1和*s2相等时两者都向后面偏移一位,前提是*s2不能等于0,若代码5的循环结束了*s2等于0,说明就找到了源代码第一次出现的位置,把cur作为函数返回值。
while ((*s1 == *s2)&& *s2) { s1++; s2++; }
(代码5)
整体的循环代码:
while (*cur) { if (*s1 != *s2) { cur++; s1 = cur; s2 = (char*)str2; } while ((*s1 == *s2)&& *s2) { s1++; s2++; } if (*s2 == 0) return cur; }
(代码6)
完整代码如下:
#include <string.h>
#include <stdio.h>
char* my_strstr(const char* str1, const char* str2)
{
char* cur =(char*) str1;
char* s1 = (char*)str1;
char* s2 = (char*)str2;
while (*cur)
{
if (*s1 != *s2)
{
cur++;
s1 = cur;
s2 = (char*)str2;
}
while ((*s1 == *s2)&& *s2)
{
s1++;
s2++;
}
if (*s2 == 0)
return cur;
}
if (*cur == 0)
return NULL;//如果找不到就让他返回空指针
}
int main()
{
char str1[] = "abcdcdefg";
char str2[] = "cde";
char* ret = my_strstr(str1, str2);//用ret指针变量存放返回的地址
printf("%s", ret);
return 0;
}
(代码7)