【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语言字符串常用函数!

相关推荐
XY_墨莲伊2 小时前
【编译原理】实验一:基于正则文法的词法分析器设计与实现
开发语言·数据结构·算法
Tirzano2 小时前
springsession全能序列化方案
java·开发语言
坐吃山猪2 小时前
Python20_MCP添加鉴权
开发语言·python
算法鑫探2 小时前
C语言实现 简易计算器教程
c语言·数据结构·算法·新人首发
gihigo19982 小时前
分布式发电的配电网有功-无功综合优化 MATLAB 实现
开发语言·分布式·matlab
人工干智能2 小时前
科普:python的pandas包中的DataFrame就是二维表
开发语言·python·pandas
浪客川2 小时前
【百例RUST - 006】一文理解所有权和切片
开发语言·后端·rust
Westward-sun.2 小时前
PyQt5入门实战:从零实现一个表达式输入式计算器(附完整代码)
开发语言·qt
喂_balabala2 小时前
Kotlin-属性委托
android·开发语言·kotlin