Namespaces
Variants

std:: strtok

From cppreference.net
定义于头文件 <cstring>
char * strtok ( char * str, const char * delim ) ;

对以空字符结尾的字节字符串进行分词处理。

一系列对 std::strtok 的调用会将 str 所指向的字符串分解为若干标记序列,每个标记均由 delim 所指向字符串中的字符进行分隔。该调用序列中的每次操作均具有一个 搜索目标 

  • 如果 str 非空,该调用是序列中的 首次调用 。搜索目标是由 str 指向的以空字符结尾的字节字符串。
  • 如果 str 为空,该调用是序列中的 后续调用 之一。搜索目标由序列中的前一次调用确定。

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

  • 如果未找到这样的字符,则搜索目标中不存在任何令牌。序列中下一次调用的搜索目标保持不变。 [1]
  • 如果找到这样的字符,它即为当前令牌的起始位置。 std::strtok 随后从该位置开始搜索首个包含在分隔符字符串中的字符。
    • 如果未找到这样的字符,当前令牌将延伸至搜索目标的末尾。序列中下一次调用的搜索目标为空字符串。 [2]
    • 如果找到这样的字符,该字符将被空字符覆盖,从而终止当前令牌。序列中下一次调用的搜索目标从后续字符开始。

如果 str delim 不是指向以空字符结尾的字节字符串的指针,则行为未定义。

  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标准库,其实现方式可能为直接实现(如 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