C strstr 函数
最后修改:2025 年 4 月 8 日
字符串操作在 C 编程中至关重要,而 strstr 是查找子字符串的关键函数。本教程将深入探讨 strstr,包括其语法、用法和潜在的陷阱。我们将探讨实际示例,并讨论对关键应用程序更安全的替代方法。理解 strstr 有助于在保持程序安全性和可靠性的同时高效地搜索字符串。
什么是 strstr?
strstr 函数用于定位字符串中子字符串的第一次出现。它在 string.h 中声明,并接受两个参数:文本字符串和要查找的子字符串。strstr 返回指向找到的子字符串的指针,如果未找到则返回 NULL。对于安全关键代码,请考虑使用带边界检查的替代方法或仔细验证输入。
基本的 strstr 用法
此示例演示了使用 strstr 查找子字符串。
#include <stdio.h>
#include <string.h>
int main() {
const char *text = "The quick brown fox jumps over the lazy dog";
const char *sub = "fox";
char *result = strstr(text, sub);
if (result != NULL) {
printf("Found '%s' at position: %ld\n", sub, result - text);
} else {
printf("'%s' not found\n", sub);
}
return 0;
}
在这里,strstr 在示例文本中搜索“fox”。该函数返回指向找到的子字符串第一个字符的指针。我们通过从文本指针中减去结果指针来计算位置。这是在 C 字符串中查找子字符串的简单有效的方法。请务必检查 NULL 返回值。
不区分大小写的搜索
此示例展示了如何使用 strstr 实现不区分大小写的搜索。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char* stristr(const char *haystack, const char *needle) {
do {
const char *h = haystack;
const char *n = needle;
while (tolower(*h) == tolower(*n) && *n) {
h++;
n++;
}
if (*n == 0) {
return (char*)haystack;
}
} while (*haystack++);
return NULL;
}
int main() {
const char *text = "C Programming Language";
const char *sub = "PROGRAMMING";
char *result = stristr(text, sub);
if (result) {
printf("Found '%s' at position: %ld\n", sub, result - text);
} else {
printf("'%s' not found\n", sub);
}
return 0;
}
这实现了 strstr 的不区分大小写的版本,称为 stristr。它在比较之前将字符转换为小写。该函数遵循与 strstr 相同的模式,但忽略大小写。请注意,这不是标准 C 库的一部分。对于生产代码,请考虑更有效的算法,如 Boyer-Moore,用于处理大文本。
查找多个出现
此示例演示了查找子字符串的所有出现。
#include <stdio.h>
#include <string.h>
int main() {
const char *text = "apple orange apple banana apple";
const char *sub = "apple";
const char *ptr = text;
int count = 0;
while ((ptr = strstr(ptr, sub)) {
printf("Found '%s' at position: %ld\n", sub, ptr - text);
ptr += strlen(sub);
count++;
}
printf("Total occurrences: %d\n", count);
return 0;
}
此代码在文本中查找“apple”的所有出现。每次找到后,它会将搜索指针移到找到的子字符串之后。循环继续,直到 strstr 返回 NULL。此技术对于计数或处理字符串中的所有匹配项很有用。请注意不要使用零长度子字符串创建无限循环。
提取分隔符之间的文本
此示例展示了如何使用 strstr 提取分隔符之间的文本。
#include <stdio.h>
#include <string.h>
int main() {
const char *text = "Data: [important] and [secret]";
const char *start_delim = "[";
const char *end_delim = "]";
const char *start = text;
const char *end;
while ((start = strstr(start, start_delim))) {
start += strlen(start_delim);
end = strstr(start, end_delim);
if (!end) break;
int length = end - start;
char extracted[256];
strncpy(extracted, start, length);
extracted[length] = '\0';
printf("Extracted: %s\n", extracted);
start = end + strlen(end_delim);
}
return 0;
}
此代码提取方括号之间的文本。它首先找到开始分隔符,然后查找结束分隔符。计算它们之间的长度并将子字符串复制到缓冲区。此模式对于解析结构化文本很有用。请务必确保您的缓冲区足够大以容纳提取的内容。
安全字符串搜索注意事项
此示例演示了带长度检查的安全字符串搜索。
#include <stdio.h>
#include <string.h>
char* safe_strstr(const char *haystack, size_t haystack_len,
const char *needle, size_t needle_len) {
if (!haystack || !needle || needle_len == 0 || haystack_len < needle_len) {
return NULL;
}
for (size_t i = 0; i <= haystack_len - needle_len; i++) {
if (strncmp(haystack + i, needle, needle_len) == 0) {
return (char*)(haystack + i);
}
}
return NULL;
}
int main() {
char buffer[256] = "Safe string handling is important";
char search[] = "string";
char *result = safe_strstr(buffer, sizeof(buffer),
search, strlen(search));
if (result) {
printf("Found '%s' at position: %ld\n", search, result - buffer);
} else {
printf("'%s' not found\n", search);
}
return 0;
}
这实现了 strstr 的更安全版本,其中包含长度检查。通过了解最大长度,它可以防止潜在的缓冲区溢出。当输入无效或要查找的字符串长于文本字符串时,该函数返回 NULL。对于安全关键应用程序,这种边界检查至关重要。这种方法比标准的 strstr 更健壮。
使用 strstr 的最佳实践
- 检查 NULL 返回值:始终验证是否找到了子字符串。
- 验证输入:确保字符串已正确空终止。
- 考虑大小写敏感性:需要时使用不区分大小写的版本。
- 注意空字符串:搜索 "" 会返回原始字符串。
- 使用边界检查:为安全关键代码实现长度检查。
来源
本教程从基本用法到高级注意事项,探讨了 strstr 函数。尽管它功能强大,但请始终小心使用字符串操作,以防止程序中的安全漏洞和未定义行为。
作者
列表 C 标准库。