strspn 是C语言标准库中的一个函数,定义在
函数原型
size_t strspn(const char *str, const char *accept);
功能:
像安检员一样,检查字符串str开头的字符是否全部在accept集合中,并返回连续通过安检的字符数量,直到发现第一个“违禁品”(不在集合中的字符)为止。
入口参数:安检规则
- str - 待检查的字符串(排队人群)
- 类型:const char*
- 必须是以\0结尾的有效字符串
- 示例:"2023Oct25"(需要检查开头是否全为数字)
- accept - 允许的字符集合(白名单)
- 类型:const char*
- 可随意组合字符,如"0123456789"或"+-"
- 示例:"0123456789"(只允许数字通过)
返回参数:安检报告
- 返回值:通过安检的连续字符数量
size_t count = strspn("123abc", "0123456789"); // 返回3("123"全为数字)
- 极端情况:
- 若第一个字符就不符合,返回0
- 若整个字符串都符合,返回字符串长度
实战用法:三大安检场景
场景1:验证数据格式(数字开头检测)
char input[] = "4567_Invalid";
size_t num_len = strspn(input, "0123456789");
if (num_len > 0) {
printf("前缀包含%zu位数字\n", num_len); // 输出:前缀包含4位数字
printf("剩余内容:%s\n", input + num_len); // 输出:_Invalid
} else {
printf("开头无数字!");
}
场景2:提取合法字符(解析命令行参数)
char cmd[] = "++--+-file=test.txt";
size_t op_len = strspn(cmd, "+-"); // 连续的操作符长度
if (op_len > 0) {
printf("操作符组合:%.*s\n", (int)op_len, cmd); // 输出:++--+-
printf("参数内容:%s\n", cmd + op_len); // 输出:file=test.txt
}
场景3:分割混合数据(分离数字与字母)
char data[] = "FF88FF#HexValue";
size_t hex_prefix = strspn(data, "0123456789ABCDEF");
printf("十六进制部分:%.*s\n", (int)hex_prefix, data); // 输出:FF88FF
printf("分隔符及后续:%s\n", data + hex_prefix); // 输出:#HexValue
高阶技巧:安检员工具箱
- 动态生成白名单(灵活安检规则)
// 生成所有小写字母的白名单
char lowercase[27];
for (int i = 0; i < 26; i++) {
lowercase[i] = 'a' + i;
}
lowercase[26] = '\0';
size_t letters = strspn("hello123", lowercase); // 返回5
- 组合使用strspn和strcspn(双重安检)
char text[] = "name=value;comment";
// 先找合法字符(字母和等号)
size_t key_len = strspn(text, "abcdefghijklmnopqrstuvwxyz=");
// 再找分隔符位置
size_t sep_pos = strcspn(text, ";");
printf("键值对:%.*s\n", (int)sep_pos, text); // 输出:name=value
printf("分隔符:%c\n", text[sep_pos]); // 输出:;
- 验证字符串纯数字(增强版)
int is_all_digits(const char *str) {
return strspn(str, "0123456789") == strlen(str);
}
// 使用示例:
printf("%d\n", is_all_digits("12345")); // 1(真)
printf("%d\n", is_all_digits("12a45")); // 0(假)
注意事项:安检漏洞
- 区分大小写
size_t len = strspn("Hello", "helo"); // 返回0,因为H大写不在小写集合中
- 白名单顺序无关
// 以下两种写法等价
strspn(str, "abc");
strspn(str, "cba");
- 包含终止符问题
char str[] = "123\0456"; // 含有\0的字符串
size_t len = strspn(str, "0123456789");
// 返回3(遇到\0终止,即使后面还有数字)
手写strspn:理解安检流程
size_t my_strspn(const char *str, const char *accept) {
size_t count = 0;
// 遍历主字符串
while (*str) {
const char *a = accept;
// 检查当前字符是否在白名单
while (*a) {
if (*str == *a) break;
a++;
}
if (!*a) return count; // 发现非法字符
count++;
str++;
}
return count; // 全部字符合法
}
对比表格:选择合适的安检方案
特性 | strspn | 手动循环检查 | 正则表达式 |
代码简洁性 | 高(一行代码) | 中(需写循环) | 高(但需要库支持) |
执行效率 | 高(库函数优化) | 中 | 低 |
灵活性 | 只能检查前缀 | 可自定义检查逻辑 | 支持复杂模式匹配 |
学习成本 | 低 | 低 | 高 |
通过这个“字符串安检指南”,你可以轻松使用strspn为字符串设置安全关卡,精准识别合法字符前缀!下次需要验证数据格式时,记得调用你的“安检员”♂!