命名空间
变体
操作

std::strtok

来自 cppreference.cn
< cpp‎ | string‎ | byte
在头文件 <cstring> 中定义
char* strtok( char* str, const char* delim );

对空终止的字节字符串进行分词。

std::strtok 进行一系列调用,将由 str 指向的字符串分解为一系列词元,每个词元都由 delim 指向的字符串中的字符分隔。序列中的每次调用都有一个 搜索目标

  • 如果 str 非空,则该调用是序列中的 首次调用。搜索目标是由 str 指向的空终止字节字符串。
  • 如果 str 为空,则该调用是序列中的 后续调用 之一。搜索目标由序列中的上一次调用决定。

序列中的每次调用都会在搜索目标中查找第一个包含在由 delim 指向的分隔符字符串中的字符,分隔符字符串可以随每次调用而不同。

  • 如果没有找到这样的字符,则搜索目标中没有词元。序列中下一次调用的搜索目标保持不变。[1]
  • 如果找到这样的字符,它就是当前词元的开头。然后 std::strtok 从那里开始搜索第一个包含在分隔符字符串中的字符。
    • 如果没有找到这样的字符,当前词元延伸到搜索目标的末尾。序列中下一次调用的搜索目标是一个空字符串。[2]
    • 如果找到这样的字符,它将被空字符覆盖,该空字符终止当前词元。序列中下一次调用的搜索目标从下一个字符开始。

如果 strdelim 不是指向空终止字节字符串的指针,则行为未定义。

  1. 词元仍然可以在后续调用中使用不同的分隔符字符串形成。
  2. 后续调用中无法再形成更多词元。

目录

[编辑] 参数

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 库,在 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 << "\nContents of the input string now:\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" 
Contents of the input string now:
"one\0+ two\0* (three\0- four\0!\0"

[编辑] 另请参阅

查找分隔符集中任何字符的第一个位置
(函数) [编辑]
返回由另一个字节字符串中找到的字符组成的最大初始段的长度
仅由另一个字节字符串中未找到的字符组成
(函数) [编辑]
返回由另一个字节字符串中找到的字符组成的最大初始段的长度
的字符
(函数) [编辑]
一个 view,包含通过分隔符拆分另一个 view 获得的子范围
(类模板) (范围适配器对象)[编辑]
C 文档 用于 strtok