std::strtok
来自cppreference.com
在标头 <cstring> 定义
|
||
char* strtok( char* str, const char* delim ); |
||
寻找 str 所指向的空终止字节字符串中的下个记号。由 delim 所指向的空终止字节字符串鉴别分隔字符。
此函数被设计为,需要进行多次调用以从同一字符串获得相继的记号。
- 若 str 不是空指针,则调用被当做
strtok
对此特定字符串的首次调用。函数搜索首个不包含于 delim 的字符。
- 若找不到这种字符,则 str 中完全没有记号,而函数返回空指针。
- 若找到这种字符,则它是记号的起始。然后函数从此处继续搜索首个包含于 delim 的字符。
- 若找不到这种字符,则 str 只有一个记号,而将来对
strtok
的调用将返回空指针。 - 若找到这种字符,则用空字符 '\0' 替换它,并将指向下个字符的指针存储于静态位置,以为后继调用所用。
- 若找不到这种字符,则 str 只有一个记号,而将来对
- 然后函数返回指向记号起始的指针。
- 若 str 为空指针,则将调用当做对
strtok
的后继调用:函数从先前调用中它剩下的位置开始。行为如同将先前存储的指针作为 str 传递。
参数
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 (类模板) (范围适配器对象) |