strstr()是 C 标准库中用于字符串查找的核心函数,作用是在一个字符串(主串)中查找另一个字符串(子串)的首次出现位置,返回指向该位置的指针;若未找到则返回NULL。
一、核心定义
1. 函数原型与头文件
#include <string.h> // 必须包含的头文件 char *strstr(const char *haystack, const char *needle);
- 参数:
haystack:待查找的主字符串(被搜索的字符串,字面意思 “干草堆”);needle:要查找的子字符串(字面意思 “针”);
- 返回值:
- 找到:返回指向
haystack中needle首次出现的起始位置的指针; - 未找到:返回
NULL; - 特殊情况:若
needle是空字符串"",则返回haystack本身(标准规定)。
- 找到:返回指向
2. 核心特性
- 匹配是大小写敏感的(如
"abc"无法匹配"ABC"); - 匹配的是连续字符序列,不支持正则表达式;
- 不修改原字符串(参数用
const修饰)。
二、基础用法示例
1. 基本查找(找到子串)
#include <stdio.h> #include <string.h> int main() { const char *main_str = "Hello, world! This is a test."; const char *sub_str = "world"; // 查找子串 char *result = strstr(main_str, sub_str); if (result != NULL) { // 输出匹配结果:找到的子串内容 printf("找到子串:%s\n", result); // 计算子串在主串中的偏移位置 int pos = result - main_str; printf("子串起始位置:第 %d 个字符(从0开始)\n", pos); } else { printf("未找到子串\n"); } return 0; }
输出结果:
找到子串:world! This is a test. 子串起始位置:第 7 个字符(从0开始)
2. 未找到子串的情况
#include <stdio.h> #include <string.h> int main() { const char *main_str = "Hello, C language!"; const char *sub_str = "Python"; char *result = strstr(main_str, sub_str); if (result == NULL) { printf("未找到子串 \"%s\"\n", sub_str); } return 0; }
输出结果:
未找到子串 "Python"
3. 查找空字符串(特殊情况)
#include <stdio.h> #include <string.h> int main() { const char *main_str = "Test string"; char *result = strstr(main_str, ""); // 子串为空 if (result == main_str) { printf("空字符串匹配成功,返回主串首地址:%p\n", result); } return 0; }
三、进阶用法
1. 查找所有匹配的子串
通过循环调用strstr(),每次从上次匹配位置的下一个字符开始查找:
#include <stdio.h> #include <string.h> int main() { char main_str[] = "abababab"; // 注意:不能用 const,否则后续指针操作会报错 const char *sub_str = "ab"; char *pos = main_str; int count = 0; while ((pos = strstr(pos, sub_str)) != NULL) { count++; printf("第 %d 次匹配位置:%ld\n", count, pos - main_str); pos += strlen(sub_str); // 跳过当前匹配的子串,避免重复匹配 } printf("总匹配次数:%d\n", count); return 0; }
输出结果:
第 1 次匹配位置:0 第 2 次匹配位置:2 第 3 次匹配位置:4 第 4 次匹配位置:6 总匹配次数:4
四、注意事项(避坑重点)
1. 空指针与空字符串
- 若传入
haystack或needle为NULL,行为未定义(可能崩溃),需提前校验。
// 安全校验示例 char *safe_strstr(const char *h, const char *n) { if (h == NULL || n == NULL) return NULL; return strstr(h, n); }
- 若
needle为空字符串,严格按标准应返回haystack,但部分老旧编译器可能行为异常,需注意兼容。
2. 原字符串不可修改的情况
若haystack是字符串常量(如const char *s = "abc"),返回的指针仅可读,不可写;若需修改匹配位置的内容,需先将字符串拷贝到可写内存(如字符数组)。
3. 重叠字符串匹配
strstr()不处理 “重叠匹配”(如主串"aaaa"查找"aa",默认只匹配 0、2 位置,而非 0、1、2 位置),若需重叠匹配,需手动调整每次查找的偏移量(仅pos += 1而非pos += strlen(needle))。
4. 宽字符版本
若处理宽字符串(wchar_t),需使用wcsstr()函数(头文件仍为<string.h>或<wchar.h>):
#include <stdio.h> #include <wchar.h> #include <locale.h> // 设置本地化,支持宽字符输出 int main() { setlocale(LC_ALL, "zh_CN.UTF-8"); // 必须设置,否则宽字符输出乱码 const wchar_t *main_wstr = L"你好,世界!世界很美好"; const wchar_t *sub_wstr = L"世界"; wchar_t *result = wcsstr(main_wstr, sub_wstr); if (result != NULL) { wprintf(L"找到宽字符子串:%ls\n", result); } return 0; }
五、总结
| 特性 | 说明 |
|---|---|
| 核心功能 | 在主串中查找子串首次出现的位置 |
| 返回值 | 匹配位置指针 / NULL(未找到) |
| 大小写 | 敏感,需自定义实现忽略大小写的版本 |
| 特殊情况 | 空子串返回主串首地址 |
| 宽字符版本 | wcsstr()(处理wchar_t字符串) |