C语言 strtok()和strtok_r()
时间: 2024-09-25 11:00:38 浏览: 37
`strtok()` 和 `strtok_r()` 都是在 C 语言标准库函数中用于字符串处理的函数,主要用于分割字符串(tokenization)。它们的主要区别在于线程安全性:
1. `strtok(char *s, const char *delim)`:这是一个单线程全局变量的版本。它接受两个参数,第一个参数 `s` 是待分割的字符串,第二个参数 `delim` 是分隔符。函数会从 `s` 开始查找分隔符,找到后将该位置之前的部分作为一次分割的结果,并替换原字符串 `s` 中的分隔符为空字符,然后返回这个结果。如果 `s` 为 `NULL`,则初始化一个内部静态变量,以便后续调用可以继续从上次的位置开始。
2. `char* strtok_r(char *s, const char *delim, char **save_ptr)`:这是线程安全的版本,也被称为 `reentrant` 版本。它需要额外的指向指针的指针 `save_ptr` 作为第三个参数,用于保存上一次分割后的位置。每次调用时,先通过这个指针获取上次的保存位置,然后继续分割。这样可以保证在多线程环境下每个线程都能独立工作,避免数据污染。
相关问题
c语言 strtok_r
`strtok_r()` 是 C 语言标准库中的一个安全版本 of `strtok()` 函数,用于按指定分隔符分割字符串。相比于 `strtok()`,它有以下几个关键优势[^1]:
1. **安全性**:`strtok_r` 不会修改全局或静态变量,这对于多线程环境至关重要,因为它避免了不同线程之间的潜在竞争条件。
2. **内存管理**:`strtok_r` 使用了一个可变参数 `&saveptr` 来保存之前 `strtok_r` 的状态,这样每次调用时都可以独立于原始字符串,从而减少了副作用。
下面是使用 `strtok_r` 的示例:
```c
#include <stdio.h>
#include <string.h>
int main() {
char string[50] = "Hello,world,this,is,a,test";
char *token;
char *saveptr;
token = strtok_r(string, ",", &saveptr);
while (token != NULL) {
printf("%s\n", token);
token = strtok_r(NULL, ",", &saveptr);
}
return 0;
}
```
在这个示例中,`strtok_r` 会返回每个找到的子串,直到整个字符串被遍历完毕或遇到空字符为止。当再次调用 `strtok_r(NULL, ",")` 时,它会从上一次停止的地方继续,除非 `saveptr` 指向了新的分隔符。
strtok和strtok_r的区别
strtok和strtok_r都是C语言中用于字符串分割的函数,它们的作用是将一个字符串按照指定的分隔符进行切割,返回切割后的子字符串。
区别在于strtok是线程不安全的函数,而strtok_r是线程安全的函数。
具体来说,strtok函数使用一个静态变量来保存上一次分割的位置,这使得strtok在多线程环境下会出现竞态条件。因此,在多线程环境下使用strtok可能会导致结果不可预测。
而strtok_r函数则不使用静态变量,而是需要显式地传递一个指向保存上一次分割位置的指针。这样,每个线程都可以使用独立的上一次分割位置,避免了竞态条件,保证了线程安全性。
总结一下:
- strtok是线程不安全的函数,使用静态变量保存上一次分割位置。
- strtok_r是线程安全的函数,需要显式地传递指向保存上一次分割位置的指针。