std::strtok
来自cppreference.com
<tbody>
</tbody>
| 在标头 <cstring> 定义
|
||
char* strtok( char* str, const char* delim ); |
||
记号化空终止字节字符串。
对 std::strtok 进行的一系列调用会将 str 指向的字符串拆分为记号序列,记号之间以 delim 中的某个字符分隔。调用序列中的每次调用都有一个搜索目标 :
- 如果
str非空,那么该调用是序列中的首次调用。搜索目标是str指向的空终止字节字符串。 - 如果
str为空,那么该调用是序列中的后续调用。搜索目标由系列中的上一次调用确定。
序列中的每次调用都会在搜索目标中搜索第一个不在 delim 指向的分隔字符串 中出现的字符,每次调用中分隔字符串可以不一致。
- 如果没有找到这种字符,那么搜索目标中没有任何记号。序列中的下次调用的搜索目标保持不变。[1]
- 如果找到了这种字符,那么它就是当前记号的起始。然后
std::strtok会从此处开始搜索第一个在分隔字符串中出现的字符。- 如果没有找到这种字符,那么当前记号会持续到搜索目标的末尾。序列中的下次调用的搜索目标是空字符串。[2]
- 如果找到了这种字符,那么会用空字符覆盖它,并结束当前记号。序列中的下次调用的搜索目标从下一字符开始。
如果 str 或 delim 不是指向空终止字节字符串的指针,那么行为未定义。
参数
| str | - | 指向要记号化的空终止字节字符串的指针 |
| delim | - | 指向标识分隔符的空终止字节字符串的指针 |
返回值
指向下个记号起始的指针,或若无更多记号则为空指针。
注解
此函数是破坏性的:它在字符串 str 的元素中写入 '\0' 字符。特别是,字符串字面量不能用作 std::strtok 的首个实参。
每次对此函数的调用都会修改静态对象:它不是线程安全的。
与大多数其他记号化器不同,std::strtok 中的分隔符对于各个后继记号可以有所不同,它甚至能依赖于先前记号的内容。
可能的实现
char* strtok(char* str, const char* delim)
{
static char* buffer;
if (str != nullptr)
buffer = str;
buffer += std::strspn(buffer, delim);
if (*buffer == '\0')
return nullptr;
char* const tokenBegin = buffer;
buffer += std::strcspn(buffer, delim);
if (*buffer != '\0')
*buffer++ = '\0';
return tokenBegin;
}
|
这个函数的实际 C++ 库实现都委托给 C 库,其中会直接实现它(如 MUSL libc),或以它的可重入版本实现(如 GNU libc)。
示例
运行此代码
#include <cstring>
#include <iomanip>
#include <iostream>
int main()
{
char input[] = "one + two * (three - four)!";
const char* delimiters = "! +- (*)";
char* token = std::strtok(input, delimiters);
while (token)
{
std::cout << std::quoted(token) << ' ';
token = std::strtok(nullptr, delimiters);
}
std::cout << "\n输入字符串的内容现在是:\n\"";
for (std::size_t n = 0; n < sizeof input; ++n)
{
if (const char c = input[n]; c != '\0')
std::cout << c;
else
std::cout << "\\0";
}
std::cout << "\"\n";
}
输出:
"one" "two" "three" "four"
输入字符串的内容现在是:
"one\0+ two\0* (three\0- four\0!\0"
参阅
| 寻找任何来自分隔符集合的字符的首个位置 (函数) | |
| 返回仅由另一字节字符串中找不到的字符组成的最大起始段的长度 (函数) | |
| 返回仅由另一字节字符串中找到的字符组成的最大起始段的长度 (函数) | |
用某个分隔符切割另一 view 所获得的子范围的 view (类模板) (范围适配器对象) | |
strtok 的 C 文档
| |