#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// 原始数据
char input[] = “7,A7B1,2.0175,270.4543”;
// 定义变量
int num7 = 0;
int a_num = 0;
int b_num = 0;
double d1 = 0.0;
double d2 = 0.0;
// 分割字符串
char *token = strtok(input, ",");
// 处理第一个值(7)
if (token) num7 = atoi(token);
// 处理第二个值(A7B1)
if ((token = strtok(NULL, ","))) {
char *a_ptr = strchr(token, 'A');
char *b_ptr = strchr(token, 'B');
if (a_ptr && *(a_ptr+1)) a_num = atoi(a_ptr+1);
if (b_ptr && *(b_ptr+1)) b_num = atoi(b_ptr+1);
}
// 处理第三个值(2.0175)
if ((token = strtok(NULL, ","))) d1 = atof(token);
// 处理第四个值(270.4543)
if ((token = strtok(NULL, ","))) d2 = atof(token);
// 验证输出
printf("num7 = %d\n", num7);
printf("a_num = %d\n", a_num);
printf("b_num = %d\n", b_num);
printf("d1 = %.4f\n", d1);
printf("d2 = %.4f\n", d2);
return 0;
}
fukaiwan 16:38:22
strtok_r
是 C 语言标准库中用于分割字符串的可重入(线程安全)版本函数,定义在 <string.h>
头文件中。与 strtok
不同,它通过显式维护分割状态,避免了静态缓冲区的限制,适合多线程环境或嵌套调用场景。
函数原型
char *strtok_r(char *str, const char *delim, char **saveptr);
参数说明
str
- 首次调用时传入待分割的字符串指针,后续调用传入
NULL
。
- 首次调用时传入待分割的字符串指针,后续调用传入
delim
- 分隔符集合字符串(如
",; "
表示逗号、分号、空格均为分隔符)。
- 分隔符集合字符串(如
saveptr
- 用户维护的指针变量地址,用于记录分割进度(需初始化为
NULL
)。
- 用户维护的指针变量地址,用于记录分割进度(需初始化为
返回值
- 成功时返回当前 token 的指针。
- 无更多 token 时返回
NULL
。
核心机制
- 显式状态管理
通过saveptr
参数保存分割进度,避免strtok
的静态缓冲区问题。 - 修改原字符串
将分隔符替换为\0
,分割后的字符串与原字符串共享内存。
示例代码
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello,world;this is-a test";
char *token;
char *saveptr; // 用于保存分割状态
const char delim[] = ",; -"; // 分隔符:逗号、分号、空格、短横线
// 首次调用,传入字符串和分隔符
token = strtok_r(str, delim, &saveptr);
// 后续调用,传入 NULL 和 saveptr
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok_r(NULL, delim, &saveptr);
}
return 0;
}
输出:
Token: Hello
Token: world
Token: this
Token: is
Token: a
Token: test
关键注意事项
- 线程安全
每个线程使用独立的saveptr
变量,避免竞争条件。 - 原字符串修改
若需保留原字符串,应先复制(如用strdup
):char *copy = strdup(original_str); // 使用 copy 分割 free(copy); // 释放内存
- 连续分隔符
多个连续分隔符视为单个分隔符(如"a,,b"
分割为"a"
和"b"
)。 - 嵌套调用
支持在递归或嵌套循环中分割多个字符串,只需为每个字符串分配独立的saveptr
。
对比 strtok
与 strtok_r
特性 | strtok | strtok_r |
---|---|---|
线程安全 | ? 否 | ? 是 |
静态缓冲区 | ? 是(潜在风险) | ? 否(用户管理状态) |
适用场景 | 单线程简单分割 | 多线程/嵌套分割 |
典型应用场景
- 多线程环境下分割字符串(如日志解析)。
- 同时处理多个字符串(如嵌套解析
"key=value1,value2"
和"name=John;age=30"
)。