????????strstr函数是一个内置函数,用于在一个字符串(haystack)中查找另一个子字符串(needle)。当找到子字符串时,它会返回该子字符串在主字符串中的起始地址。今天,我们将通过一个自定义实现的my_strstr
函数来详细解析这一过程。
// 定义一个名为my_strstr的自定义函数,功能类似于C标准库中的strstr函数,用于在字符串p1中查找字符串p2
char* my_strstr(const char* p1, const char* p2) {
// 使用assert断言确保输入的两个字符串指针都不指向空字符,即都不是空字符串
assert(*p1 && *p2);
// 初始化三个字符指针:s1,s2和stu,其中stu初始指向p1的首地址
char* s1 = NULL;
char* s2 = NULL;
char* stu = (char*)p1;
// 特殊情况:如果p2为空字符串(只包含结束符'\0'),则返回p1的首地址
if (*p2 == '\0') {
return (char*)p1;
}
// 主循环,遍历字符串p1直到遇到结束符'\0'
while (*stu) {
// 将s1和s2分别指向stu和p2的当前字符,开始新一轮的比较
s1 = stu;
s2 = (char*)p2;
// 内部循环,逐个比较s1和s2指向的字符,如果相同则继续比较下一个字符
// 直到遇到任意一个字符串的结束符'\0'或者发现不相等的字符为止
while (*s1 && *s2 && (*s1 == *s2)) { // '\0'的ASCII码值是0,视为假
s1++;
s2++;
}
// 如果s2已经指向结束符'\0',则说明在stu开始的位置找到了子串p2,返回stu
if (*s2 == '\0') {
return stu; // 找到子串p2
}
// 如果s1已经指向结束符'\0',说明当前stu所在子串长度不足以匹配p2,终止本次查找
if (*s1 == '\0') {
return NULL;
}
// 移动stu指针,使其指向下一个可能的子串起始位置
*stu++;
}
// 遍历结束后仍未找到子串p2,则返回NULL
return NULL; // 没找到
}
int main() {
// 定义两个字符串arr1和arr2作为测试数据
char* arr1 = "abcdabcd";
char* arr2 = "bcdaaaaaas";
// 调用自定义my_strstr函数查找arr1中是否存在arr2子串
const char* ret = my_strstr(arr1, arr2);
// 根据返回值判断查找结果
if (ret == NULL) {
printf("没找到");
} else {
printf("%s\n", ret); // 输出找到的子串在主串中的起始位置
}
// 主函数返回0,表示程序正常执行完毕
return 0;
}
my_strstr
函数接受两个const char*
类型的指针作为输入参数:p1
是指向待搜索的主字符串,p2
是指向需查找的子字符串。函数返回一个char*
类型的指针,指向子字符串在主字符串中的起始位置,若未找到子字符串,则返回NULL。
assert
宏确保输入的主字符串和子字符串都不为空。然后初始化三个字符指针s1
、s2
和stu
,其中s1
和s2
将在后续用于遍历主字符串和子字符串,stu
初始设置为主字符串的起始地址。p2
的第一个字符就是结束符\0
,说明子字符串为空,按照strstr函数的行为规范,直接返回主字符串p1
的地址。stu
指针依次指向每个可能的子串起始位置。s1
指向stu
的当前位置,s2
指向子字符串的起始位置。s1
和s2
,在两者的字符相等且非空的情况下,递进至下一个字符。s2
到达子字符串的结束符\0
时,说明找到了一个完整的子字符串匹配,此时返回s1
的初始位置(即stu
)。s1
先到达结束符,意味着当前子串不能与子字符串完全匹配,跳过内层循环继续搜索。stu
指针前进一位,以便检查下一段可能的子串。int main() {
char* arr1 = "abcdabcd";
char* arr2 = "bcdaaaaaas";
const char* ret = my_strstr(arr1, arr2);
if (ret == NULL) {
printf("没找到");
} else {
printf("%s\n", ret);
}
return 0;
}
输出结果: