【C标准库】深入理解C语言strstr函数:子字符串查找的实用指南


🌈个人主页:聆风吟_
🔥系列专栏:C语言标准库
🔖少年有梦不应止于心动,更要付诸行动。


文章目录

📋前言

在 C 语言的字符串处理中,strstr 函数是查找子字符串最常用的工具之一。它能帮我们快速定位一个字符串在另一个字符串中首次出现的位置,无论是文本处理、日志解析还是日常开发,都离不开它。

这篇博客会从函数原型、参数含义、返回值、使用示例、底层实现注意事项 ,全方位带你吃透 strstr,新手也能轻松掌握。


一、strstr 函数基础

strstr 是 C 标准库 <string.h> 中的函数,核心功能 :在一个主字符串 中查找子字符串 首次出现的位置(不匹配字符串结束符 \0)。

1.1 函数原型

c 复制代码
#include <string.h>  // 必须包含的头文件

char *strstr(const char *haystack, const char *needle);

1.2 参数解释

  • haystack:要搜索的 "主字符串"(干草堆)
  • needle:要查找的 "子字符串"(针)

简单记忆:在干草堆(haystack)里找针(needle),非常形象。

1.3 返回值

  • 匹配成功 :返回子字符串在主串中首次出现的地址(指针);
  • 匹配失败 :返回 NULL
  • 特殊情况 :如果子字符串是空字符串(""),直接返回主字符串的首地址。

二、基础使用示例

先看几个简单例子,快速掌握 strstr 的基本用法。

示例1:基础子串查找

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    // 主字符串
    const char* str = "Hello, welcome to C language!";
    // 要查找的子串
    const char* sub_str = "welcome";

    // 查找子串
    char* result = strstr(str, sub_str);

    // 判断结果
    if (result != NULL)
    {
        printf("找到子串!位置:%s\n", result);
    }
    else
    {
        printf("未找到子串\n");
    }

    return 0;
}

输出结果

复制代码
找到子串!位置:welcome to C language!

因为 strstr 返回的是子串首次出现的地址,所以从该地址打印字符串,会从子串开始一直输出到主串末尾。

示例2:子串不存在

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    const char* str = "I love programming";
    const char* sub_str = "C++";

    char* result = strstr(str, sub_str);

    if (result)
    {
        printf("找到:%s\n", result);
    }
    else
    {
        printf("未找到子串 C++\n");
    }

    return 0;
}

输出结果

复制代码
未找到子串 C++

示例3:子串为空字符串

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    const char* str = "Test string";
    const char* sub_str = "";

    // 子串为空
    char* result = strstr(str, sub_str);

    printf("结果:%s\n", result);

    return 0;
}

输出结果

复制代码
结果:Test string

这是 C 标准规定的行为:空字符串是任何字符串的子串。


三、进阶用法:获取子串偏移位置

实际开发中,我们不仅想知道是否找到子串,还想知道子串在主串中的下标(偏移量)

利用指针运算即可实现:

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    const char* str = "abcdef123456";
    const char* sub_str = "123";

    char* result = strstr(str, sub_str);

    if (result != NULL)
    {
        // 指针相减,得到子串的起始下标
        int pos = result - str;
        printf("子串在主串的第 %d 个位置\n", pos);
    }

    return 0;
}

输出结果

复制代码
子串在主串的第 6 个位置

四、手动实现 strstr 函数(理解底层逻辑)

想真正吃透 strstr,最好的方式是自己实现一遍。核心逻辑:

  1. 遍历主字符串,逐个字符和子串首字符匹配;
  2. 匹配到首字符后,继续校验后续字符是否完全一致;
  3. 完全匹配则返回当前地址,否则继续遍历。
c 复制代码
#include <stdio.h>
#include <string.h>

// 手动实现 strstr
char* my_strstr(const char* haystack, const char* needle)
{
    // 子串为空,直接返回主串
    if (*needle == '\0')
    {
        return (char*)haystack;
    }

    // 遍历主串
    while (*haystack)
    {
        const char* h = haystack;
        const char* n = needle;

        // 逐个匹配字符
        while (*h && *n && (*h == *n))
        {
            h++;
            n++;
        }

        // 子串匹配完毕,找到目标
        if (*n == '\0')
        {
            return (char*)haystack;
        }

        haystack++;
    }

    // 未找到
    return NULL;
}

// 测试
int main()
{
    char str[] = "hello world";
    char sub[] = "world";

    char* res = my_strstr(str, sub);
    if (res)
    {
        printf("自定义函数找到:%s\n", res);
    }

    return 0;
}

输出结果

复制代码
自定义函数找到:world

五、使用 strstr 的注意事项

  1. 必须包含头文件 <string.h>

    不包含头文件会导致函数未声明,编译报警/报错。

  2. 区分大小写
    strstr大小写敏感 的,比如查找 "Hello" 不会匹配 "hello"

    若需要忽略大小写匹配,需要自己实现逻辑(转换为小写/大写后再比较)。

  3. 参数不能是 NULL

    如果传入 NULL 作为主串或子串,会直接导致程序崩溃 (段错误)。

    建议使用前做判空:

    c 复制代码
    if (haystack == NULL || needle == NULL)
    {
        return NULL;
    }
  4. 只返回首次匹配的位置

    如果主串中有多个子串,strstr 只返回第一个的地址。


📝全文总结

strstr 是 C 语言字符串处理的高频核心函数,总结一下关键点:

  1. 作用:在主串中查找子串首次出现的位置;
  2. 原型:char *strstr(const char *haystack, const char *needle);
  3. 返回:匹配成功返回地址,失败返回 NULL
  4. 特性:区分大小写、子串为空返回主串、参数不可为 NULL
  5. 拓展:通过指针相减可获取子串在主串中的下标。

掌握 strstr,能帮你轻松解决大部分字符串查找问题,是 C 语言开发者必备技能!

如果这篇文章对你有帮助,欢迎点赞收藏~ 下期我们继续拆解C语言字符串常用函数!

相关推荐
傻啦嘿哟3 小时前
某招聘平台爬虫:爬取招聘岗位数据,分析各城市薪资水平
开发语言·爬虫·python
2501_933670793 小时前
2026秋招量化分析岗技能栈:Python、SQL、统计建模、回测项目怎么准备
开发语言·python·sql
李少兄4 小时前
JavaScript 数据类型完全指南
开发语言·javascript·ecmascript
Seoyoneh4 小时前
Agentic Workflow编排架构:云客服从“被动响应”迈向“主动执行”的技术实现
java·开发语言·架构
Tangyuewei5 小时前
Java 写 Agent:模型只是组件
java·开发语言
小玮看世界5 小时前
[Python]从合并区间到传感器融合区:合并区间在传感器区域融合的实际落地
开发语言·python
繁星蓝雨6 小时前
C++的设计与演进大纲(如何从C语言一步步成长为C++)
c语言·开发语言·c++·c++历史·c++演进
Evand J6 小时前
【MATLAB例程,图像降噪滤波9】自适应维纳滑动窗口滤波(Wiener)图像降噪、方法对比,有中文注释
开发语言·图像处理·计算机视觉·matlab·滑动窗口·滤波·降噪
yutian06066 小时前
C: Unix UTC 时间戳转为 UTC+8 北京时间
c语言·unix
杜大哥7 小时前
python程序:如何查看电脑【电池电量的剩余百分比】 和 【是否插入连接着充电器】?
开发语言·python