这是一篇介绍字符串函数strstr模拟实现的博客,包括有strstr在MSDN中的详细介绍,每一步实现的思路与方法,以及一些易错点的提醒。
一、strstr在MSDN中的注解
寻找一个子字符串; 注解中,仅用一个简单的句子就描述了函数的作用,但这并不能让我们充分了解strstr,我们接着一步一步向下看;
1、返回值
两种情况:当string中存在Charset时,返回Charset在string第一次出现的地址;当string中不存在Charset时,返回空指针;还有一种特殊情况,当Charset指向的字符串为0长度时,返回string的地址。
2、参数
- string 以Null结尾的,要搜索的字符串;
- strCharset 以Null结尾的,被搜索的字符串;
这么简单翻译,其实不好理解;说人话就是,要在字符串string中寻找字符串strCharset,而这两个字符串都必须以Null结尾,也就是说,以'\0'结尾。
3、标注
strstr函数返回一个指向strCharset在string中首次出现的地址,函数的搜索不会包括结尾的'\0'。 到这,相信大家对strstr函数的具体作用已经大致了解,其实它就是一个字符串查找函数;举个活灵活现的例子: 你妈叫你去仓库(这个仓库就是string)找一罐辣椒(strCharset),你找到了就告诉她在哪里(返回一个指针,这个指针指向string中的一个位置,这个位置就是strCharset第一次出现的位置),没找到就说没有(返回空指针)。
二、strstr的模拟实现
举个小例子 string字符串为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'。