strstr 函数使用教程:C/C++ 字符串查找实例
在 C/C++ 编程中,字符串查找是一个非常常见的操作。strstr 函数是 C 标准库中用于在一个字符串中查找另一个字符串的函数。本文将详细介绍 strstr 函数的定义、使用方法、实例以及在使用时需要注意的事项。
1. strstr 函数概述
strstr 函数(string-string)用于在给定字符串(haystack)中查找第一个出现的子字符串(needle)。它是 C 语言标准库 <string.h>(在 C++ 中是 <cstring>)的一部分。
函数原型:
c
char *strstr(const char *haystack, const char *needle);
参数说明:
haystack: 指向要搜索的 C 风格字符串的指针。needle: 指向要查找的子字符串的指针。
返回值:
- 如果
needle字符串在haystack字符串中找到,strstr函数返回一个指向haystack中needle第一次出现位置的指针。 - 如果
needle字符串没有在haystack字符串中找到,函数返回NULL。 - 如果
needle是一个空字符串(""),函数返回haystack本身。
2. strstr 函数的工作原理
strstr 函数从 haystack 字符串的开头开始,逐个字符地与 needle 字符串进行比较。一旦找到一个匹配 needle 完整长度的序列,它就返回该匹配的起始位置。查找过程是区分大小写的。
3. C 语言使用实例
以下是一个简单的 C 语言示例,演示如何使用 strstr 函数查找子字符串。
“`c
include
include // 包含 strstr 函数的头文件
int main() {
const char text = “Hello, world! This is a test string.”;
const char sub1 = “world”;
const char sub2 = “example”;
const char sub3 = “string”;
const char *sub4 = “”; // 空字符串
char *result;
// 查找 "world"
result = strstr(text, sub1);
if (result != NULL) {
printf("'%s' found in '%s' at position: %ld\n", sub1, text, result - text);
// 输出从匹配位置开始的子字符串
printf("Substring from match: '%s'\n", result);
} else {
printf("'%s' not found in '%s'\n", sub1, text);
}
// 查找 "example" (不存在)
result = strstr(text, sub2);
if (result != NULL) {
printf("'%s' found in '%s' at position: %ld\n", sub2, text, result - text);
} else {
printf("'%s' not found in '%s'\n", sub2, text);
}
// 查找 "string"
result = strstr(text, sub3);
if (result != NULL) {
printf("'%s' found in '%s' at position: %ld\n", sub3, text, result - text);
} else {
printf("'%s' not found in '%s'\n", sub3, text);
}
// 查找空字符串
result = strstr(text, sub4);
if (result != NULL) {
printf("Empty string found at the beginning of '%s'. Result pointer: %p, text pointer: %p\n", text, (void*)result, (void*)text);
// 验证返回的是否是 haystack 本身
if (result == text) {
printf("As expected, searching for an empty string returns the original string pointer.\n");
}
}
return 0;
}
“`
输出示例:
'world' found in 'Hello, world! This is a test string.' at position: 7
Substring from match: 'world! This is a test string.'
'example' not found in 'Hello, world! This is a test string.'
'string' found in 'Hello, world! This is a test string.' at position: 29
Empty string found at the beginning of 'Hello, world! This is a test string.'. Result pointer: 0x... , text pointer: 0x...
As expected, searching for an empty string returns the original string pointer.
在上面的示例中,result - text 计算了子字符串在主字符串中的起始偏移量(位置)。
4. C++ 语言使用实例
在 C++ 中,虽然可以使用 <cstring> 包含 strstr 函数,但更推荐使用 std::string 类的成员函数 find(),因为它更符合 C++ 的面向对象特性,并且处理内存和空终止符更安全。然而,如果处理的是 C 风格字符串(const char*),strstr 仍然是一个有效且常用的选择。
“`cpp
include
include // 包含 strstr 函数的头文件
include // 包含 std::string 类
int main() {
// 使用 C 风格字符串和 strstr
const char text_c = “C++ programming is powerful.”;
const char sub_c = “programming”;
char *result_c = std::strstr(text_c, sub_c);
if (result_c != nullptr) {
std::cout << "C-style: '" << sub_c << "' found at position: " << result_c - text_c << std::endl;
std::cout << "Substring from match: '" << result_c << "'\n" << std::endl;
} else {
std::cout << "C-style: '" << sub_c << "' not found." << std::endl;
}
// 使用 std::string 和其 find() 方法 (C++ 推荐方式)
std::string text_cpp = "C++ programming is powerful.";
std::string sub_cpp = "powerful";
std::string sub_not_found = "java";
size_t pos = text_cpp.find(sub_cpp);
if (pos != std::string::npos) { // std::string::npos 表示未找到
std::cout << "C++ std::string: '" << sub_cpp << "' found at position: " << pos << std::endl;
std::cout << "Substring from match: '" << text_cpp.substr(pos) << "'\n" << std::endl;
} else {
std::cout << "C++ std::string: '" << sub_cpp << "' not found." << std::endl;
}
pos = text_cpp.find(sub_not_found);
if (pos != std::string::npos) {
std::cout << "C++ std::string: '" << sub_not_found << "' found at position: " << pos << std::endl;
} else {
std::cout << "C++ std::string: '" << sub_not_found << "' not found." << std::endl;
}
return 0;
}
“`
输出示例:
“`
C-style: ‘programming’ found at position: 4
Substring from match: ‘programming is powerful.’
C++ std::string: ‘powerful’ found at position: 21
Substring from match: ‘powerful.’
C++ std::string: ‘java’ not found.
“`
5. 注意事项和常见问题
- 空字符串
needle: 如前所述,如果needle是一个空字符串"",strstr会返回haystack指针本身。这通常被视为needle在haystack的开头被找到。 - 区分大小写:
strstr是区分大小写的。例如,在 “Hello World” 中查找 “world” 会失败。如果需要不区分大小写的查找,你需要手动实现一个版本,或者将两个字符串都转换为相同的大小写(例如,都转换为小写)后再进行比较。 NULL参数: 如果haystack或needle中的任何一个为NULL,调用strstr将导致未定义行为(通常是程序崩溃)。在使用strstr之前,始终确保参数是非空指针。- 返回指针的修改:
strstr返回的指针指向haystack内部的内存。如果你通过这个指针修改数据,你将修改原始的haystack字符串。请务必小心。 - C++ 推荐
std::string::find: 在 C++ 中,当使用std::string对象时,强烈建议使用std::string::find()方法。它提供了类型安全、自动内存管理和更直观的接口。
6. strstr 的替代方案
- C++
std::string::find(): 对于std::string对象,这是最推荐的字符串查找方法。它返回子字符串的起始索引,而不是指针,并且查找失败时返回std::string::npos。 - C 语言的
strpbrk(): 如果你需要查找字符串中包含在另一个字符串中的任意一个字符,可以使用strpbrk()。 - C 语言的
strchr()和strrchr(): 如果你只需要查找单个字符的第一次或最后一次出现,这两个函数更为合适。 - 自定义实现: 对于更复杂的查找需求,例如正则表达式匹配,或者不区分大小写的查找,你可能需要使用更高级的库(如 C++ 的
<regex>)或实现自己的查找逻辑。
7. 总结
strstr 函数是 C/C++ 中一个基本且高效的 C 风格字符串查找工具。它在处理 const char* 类型的字符串时非常有用,但在 C++ 中使用 std::string 时,std::string::find() 通常是更安全和更现代的选择。理解 strstr 的工作原理、返回值和注意事项,可以帮助你编写健壮且高效的字符串处理代码。