C strspn 函数
最后修改:2025 年 4 月 8 日
字符串操作在 C 编程中至关重要,而 strspn 是分析字符串内容的关键函数。本教程将深入介绍 strspn,包括其语法、用法和实际应用。我们将通过示例探讨如何验证输入和解析字符串。理解 strspn 有助于在保持程序安全性和可靠性的同时,创建健壮的字符串处理功能。
什么是 strspn?
strspn 函数计算字符串的初始段的长度,该段完全由另一个字符串中的字符组成。它在 string.h 中声明,并接受两个参数:要检查的字符串和可接受字符的集合。strspn 返回字符串开头匹配字符的数量。为了安全起见,在处理之前务必验证输入,以防止缓冲区溢出。
strspn 的基本用法
此示例演示了 strspn 的基本用法,用于查找数字。
#include <stdio.h>
#include <string.h>
int main() {
const char *str = "12345abc";
const char *digits = "0123456789";
size_t span = strspn(str, digits);
printf("String: %s\n", str);
printf("Initial digit span: %zu\n", span);
return 0;
}
在此,strspn 扫描 str 并计算开头的多少个字符与 digits 中的字符匹配。它返回 5,因为“12345”都是数字。该函数在遇到不在数字集中的“a”时停止。这对于验证字符串格式或提取数字前缀非常有用。%zu 格式说明符可正确打印 size_t 返回值。
使用 strspn 验证输入
strspn 可以验证字符串是否只包含允许的字符。
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool is_valid_hex(const char *str) {
const char *hex_chars = "0123456789ABCDEFabcdef";
return strspn(str, hex_chars) == strlen(str);
}
int main() {
const char *test1 = "1A3F9C";
const char *test2 = "1G5H9Z";
printf("%s is %s\n", test1, is_valid_hex(test1) ? "valid" : "invalid");
printf("%s is %s\n", test2, is_valid_hex(test2) ? "valid" : "invalid");
return 0;
}
此示例检查字符串是否只包含十六进制字符。is_valid_hex 函数在整个字符串由十六进制数字组成时返回 true。strspn 扫描字符串,直到找到一个非十六进制字符。通过将跨度长度与字符串长度进行比较,我们可以验证整个输入。此技术对于清理用户输入很有用。
解析数字前缀
此示例展示了如何从字符串中提取和转换数字前缀。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
const char *data = "42apples";
const char *digits = "0123456789";
size_t num_len = strspn(data, digits);
if (num_len > 0) {
char num_str[20] = {0};
strncpy(num_str, data, num_len);
int number = atoi(num_str);
printf("Numeric prefix: %d\n", number);
printf("Remaining string: %s\n", data + num_len);
} else {
printf("No numeric prefix found\n");
}
return 0;
}
在这里,strspn 查找 data 中数字前缀的长度。然后,我们将此前缀复制到临时缓冲区并将其转换为整数。字符串的其余部分也可供进一步处理。这种方法对于解析混合格式的字符串很有用。请注意,strncpy 在具有适当大小缓冲区的安全场景下使用。
查找标记边界
strspn 可帮助识别字符串处理中的标记边界。
#include <stdio.h>
#include <string.h>
void print_tokens(const char *str, const char *delims) {
const char *ptr = str;
while (*ptr) {
size_t span = strspn(ptr, delims);
ptr += span; // Skip delimiters
size_t len = strcspn(ptr, delims);
if (len > 0) {
printf("Token: %.*s\n", (int)len, ptr);
ptr += len;
}
}
}
int main() {
const char *text = " apple, banana; cherry ";
const char *delimiters = " ,;";
print_tokens(text, delimiters);
return 0;
}
此代码同时使用 strspn 和 strcspn 对字符串进行标记。strspn 跳过前导分隔符,而 strcspn 查找下一个分隔符。这种组合有效地将字符串拆分为标记。%.*s 格式以指定长度打印子字符串。此技术对于自定义字符串解析很有用。
验证文件名
此示例演示了使用 strspn 进行文件名验证。
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool is_valid_filename(const char *name) {
const char *valid_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-_.";
if (strlen(name) == 0 || strlen(name) > 255) return false;
if (name[0] == '.') return false;
return strspn(name, valid_chars) == strlen(name);
}
int main() {
const char *test1 = "document.pdf";
const char *test2 = "bad*file.txt";
printf("%s is %s\n", test1, is_valid_filename(test1) ? "valid" : "invalid");
printf("%s is %s\n", test2, is_valid_filename(test2) ? "valid" : "invalid");
return 0;
}
此代码检查文件名是否只包含允许的字符。strspn 验证整个字符串是否由有效字符组成。其他检查可确保长度正确并防止隐藏文件(以“.”开头)。这比简单的字符搜索更健壮。始终将 strspn 与其他验证结合使用以确保完全安全。
使用 strspn 的最佳实践
- 首先验证输入:在处理之前,确保字符串以 null 结尾。
- 与其他检查结合:将长度检查与字符验证结合使用。
- 考虑区域设置:不同区域设置中的字符集可能不同。
- 用于前缀匹配:非常适合检查字符串开头是否为有效字符。
- 优于手动循环:比自定义字符扫描更易读且更优化。
来源
本教程探讨了 strspn 函数,从基本用法到高级验证技术。正确使用时,它可以提供高效的字符串分析,同时有助于防止因格式错误的输入而导致的安全问题。
作者
列表 C 标准库。