C语言实现的自定义strstr函数

发布时间:2024年01月19日

引言

????????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。

函数实现步骤
  1. 初步校验与变量初始化?使用assert宏确保输入的主字符串和子字符串都不为空。然后初始化三个字符指针s1s2stu,其中s1s2将在后续用于遍历主字符串和子字符串,stu初始设置为主字符串的起始地址。
  2. 处理特殊边界情况?如果子字符串p2的第一个字符就是结束符\0,说明子字符串为空,按照strstr函数的行为规范,直接返回主字符串p1的地址。
  3. 主循环搜索过程?使用一个外层循环遍历主字符串的所有字符,stu指针依次指向每个可能的子串起始位置。
    • 对于每个可能的子串起点,令s1指向stu的当前位置,s2指向子字符串的起始位置。
    • 内层循环同时遍历s1s2,在两者的字符相等且非空的情况下,递进至下一个字符。
    • 当内层循环使s2到达子字符串的结束符\0时,说明找到了一个完整的子字符串匹配,此时返回s1的初始位置(即stu)。
    • s1先到达结束符,意味着当前子串不能与子字符串完全匹配,跳过内层循环继续搜索。
    • 在每轮外层循环结束后,无论是否匹配成功,都将stu指针前进一位,以便检查下一段可能的子串。
  4. 未找到子字符串时的返回?若遍历完主字符串仍未能找到子字符串,则在循环结束后返回NULL。
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;
}

输出结果:

文章来源:https://blog.csdn.net/2302_78381559/article/details/135686739
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。