引言
strstr函数是一个内置函数,用于在一个字符串(haystack)中查找另一个子字符串(needle)。当找到子字符串时,它会返回该子字符串在主字符串中的起始地址。今天,我们将通过一个自定义实现的
导图
代码举例
// 定义一个名为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为空字符串(只包含结束符''),则返回p1的首地址 if (*p2 == '') { return (char*)p1; } // 主循环,遍历字符串p1直到遇到结束符'' while (*stu) { // 将s1和s2分别指向stu和p2的当前字符,开始新一轮的比较 s1 = stu; s2 = (char*)p2; // 内部循环,逐个比较s1和s2指向的字符,如果相同则继续比较下一个字符 // 直到遇到任意一个字符串的结束符''或者发现不相等的字符为止 while (*s1 && *s2 && (*s1 == *s2)) { // ''的ASCII码值是0,视为假 s1++; s2++; } // 如果s2已经指向结束符'',则说明在stu开始的位置找到了子串p2,返回stu if (*s2 == '') { return stu; // 找到子串p2 } // 如果s1已经指向结束符'',说明当前stu所在子串长度不足以匹配p2,终止本次查找 if (*s1 == '') { 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 ", ret); // 输出找到的子串在主串中的起始位置 } // 主函数返回0,表示程序正常执行完毕 return 0; }
函数定义与参数介绍
函数实现步骤
-
初步校验与变量初始化 使用
assert 宏确保输入的主字符串和子字符串都不为空。然后初始化三个字符指针s1 、s2 和stu ,其中s1 和s2 将在后续用于遍历主字符串和子字符串,stu 初始设置为主字符串的起始地址。 -
处理特殊边界情况 如果子字符串
p2 的第一个字符就是结束符,说明子字符串为空,按照strstr函数的行为规范,直接返回主字符串 p1 的地址。 -
主循环搜索过程 使用一个外层循环遍历主字符串的所有字符,
stu 指针依次指向每个可能的子串起始位置。-
对于每个可能的子串起点,令
s1 指向stu 的当前位置,s2 指向子字符串的起始位置。 -
内层循环同时遍历
s1 和s2 ,在两者的字符相等且非空的情况下,递进至下一个字符。 -
当内层循环使
s2 到达子字符串的结束符时,说明找到了一个完整的子字符串匹配,此时返回 s1 的初始位置(即stu )。 -
若
s1 先到达结束符,意味着当前子串不能与子字符串完全匹配,跳过内层循环继续搜索。 -
在每轮外层循环结束后,无论是否匹配成功,都将
stu 指针前进一位,以便检查下一段可能的子串。
-
-
未找到子字符串时的返回 若遍历完主字符串仍未能找到子字符串,则在循环结束后返回NULL。
int main() { char* arr1 = "abcdabcd"; char* arr2 = "bcdaaaaaas"; const char* ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("没找到"); } else { printf("%s ", ret); } return 0; }
输出结果: