40-c语言字符串分割
C语言标准库未提供内置字符串分割函数,主要通过
strtok()实现简单分割(会修改原字符串且非线程安全,需确保字符串存储在可修改数组中而非字面量),线程安全替代方案为strtok_r(),若需保留原字符串则可用strcspn/strspn组合或sscanf解析固定格式,实际使用中应根据场景选择方法:单线程简单任务用strtok(),多线程环境用strtok_r(),保留原字符串用组合方法。
C语言标准库没有直接提供split函数,但提供了几种实用的字符串分割方法。
1. strtok()函数(最常用方法)
函数原型
#include <string.h>
char *strtok(char *str, const char *delim);
使用方法
#include <stdio.h>
#include <string.h>
int main() {
char sentence[] = "Hello,world,this,is,a,test";
const char delimiters[] = ", ";
char *token;
// 首次调用,传入原始字符串
token = strtok(sentence, delimiters);
while (token != NULL) {
printf("%s\n", token);
// 后续调用传入NULL
token = strtok(NULL, delimiters);
}
return 0;
}
工作原理
- 首次调用时,传入目标字符串和分隔符
- 后续调用传入
NULL,继续从上次分割位置开始 - 会将分隔符替换为
\0,修改原字符串 - 自动跳过连续分隔符(如"a,,b"会被分割为"a"和"b")
重要注意事项
- 原始字符串必须可修改:不能是字符串字面量(如
char *str = "hello";),必须是数组形式(如char str[] = "hello";) - 非线程安全:使用静态变量保存分割状态,多线程环境下应使用
strtok_r() - 会修改原字符串:分割过程中会将分隔符替换为
\0,原字符串会被破坏 - 分隔符是集合:
", "表示逗号和空格都是分隔符
2. 线程安全替代方案:strtok_r()
函数原型
char *strtok_r(char *str, const char *delim, char **saveptr);
使用方法
#include <stdio.h>
#include <string.h>
int main() {
char sentence[] = "Hello,world,this,is,a,test";
const char delimiters[] = ", ";
char *token;
char *saveptr;
// 首次调用,传入原始字符串和saveptr
token = strtok_r(sentence, delimiters, &saveptr);
while (token != NULL) {
printf("%s\n", token);
// 后续调用传入NULL和相同的saveptr
token = strtok_r(NULL, delimiters, &saveptr);
}
return 0;
}
优点
- 线程安全:通过
saveptr参数显式保存分割状态 - 适合多线程环境
3. 不修改原字符串的分割方法
如果需要保留原字符串,可以使用strcspn和strspn函数组合:
#include <stdio.h>
#include <string.h>
int main() {
char sentence[] = "Hello,world,this,is,a,test";
const char delimiters[] = ", ";
char *current = sentence;
char *next;
while ((next = strpbrk(current, delimiters)) != NULL) {
// 处理当前token(从current到next)
char token[next - current + 1];
strncpy(token, current, next - current);
token[next - current] = '\0';
printf("%s\n", token);
// 移动到下一个位置
current = next + 1;
}
// 处理最后一个token
if (strlen(current) > 0) {
printf("%s\n", current);
}
return 0;
}
4. 其他方法
1. 使用sscanf()解析固定格式字符串
#include <stdio.h>
int main() {
char str[] = "894529306@qq.com";
int id;
char domain[10];
sscanf(str, "%d@%[^.]", &id, domain);
printf("用户名: %d\n", id);
printf("邮箱类型: %s\n", domain);
return 0;
}
2. 自定义分割函数
对于更复杂的需求,可以编写自己的分割函数,根据需要处理空字段、多级分割等。
5. 常见问题与解决方案
问题1:字符串字面量导致程序崩溃
// 错误用法
char *str = "hello,world";
strtok(str, ","); // 会导致程序崩溃
解决方案:使用可修改的字符数组
// 正确用法
char str[] = "hello,world";
strtok(str, ",");
问题2:处理连续分隔符
char str[] = "a,,b";
strtok(str, ","); // 会返回"a"和"b",跳过中间的空字符串
解决方案:如果需要保留空字符串,可以使用strsep()函数
总结
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| strtok() | 接口简单,高效 | 修改原字符串,非线程安全 | 简单单线程场景 |
| strtok_r() | 线程安全 | 代码稍复杂 | 多线程环境 |
| strcspn/strspn | 不修改原字符串 | 代码较长 | 需要保留原字符串的场景 |
| sscanf() | 适合固定格式解析 | 无法处理任意分隔符 | 解析特定格式数据 |
在实际开发中,对于简单的字符串分割需求,strtok()仍是很好的选择;在多线程环境或需要保留原字符串时,应选择strtok_r()或使用strcspn/strspn组合。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

