命名空间
变体
操作

strtok, strtok_s

来自 cppreference.cn
< c‎ | string‎ | byte
在头文件 <string.h> 中定义
(1)
char* strtok( char* str, const char* delim );
(直到 C99)
char* strtok( char* restrict str, const char* restrict delim );
(自 C99 起)
char* strtok_s( char* restrict str, rsize_t* restrict strmax,
                const char* restrict delim, char** restrict ptr );
(2) (自 C11 起)

将空终止字节字符串标记化。

1) 一系列对 strtok 的调用将 str 指向的字符串分解为一系列标记,每个标记都由 delim 指向的字符串中的字符分隔。序列中的每次调用都有一个搜索目标
  • 如果 str 非空,则该调用是序列中的首次调用。搜索目标是由 str 指向的空终止字节字符串。
  • 如果 str 为空,则该调用是序列中的后续调用之一。搜索目标由序列中的前一次调用确定。
序列中的每次调用都在搜索目标中搜索包含在 delim 指向的分隔符字符串中的第一个字符,分隔符字符串可能因调用而异。
  • 如果未找到此类字符,则搜索目标中没有标记。序列中下一次调用的搜索目标保持不变。[1]
  • 如果找到这样的字符,则它是当前标记的开始。然后 strtok 从那里开始搜索分隔符字符串中包含的第一个字符。
    • 如果未找到此类字符,则当前标记扩展到搜索目标的末尾。序列中下一次调用的搜索目标是空字符串。[2]
    • 如果找到这样的字符,它将被空字符覆盖,该空字符终止当前标记。序列中下一次调用的搜索目标从以下字符开始。
如果 strdelim 不是指向空终止字节字符串的指针,则行为未定义。
2)(1) 相同,但以下差异除外
  • 在每次调用中,将 str 中剩余要查看的字符数写入 *strmax,并将 tokenizer 的内部状态写入 *ptr
  • 序列中的后续调用必须传递 strmaxptr,其值为前一次调用存储的值。
  • 以下错误在运行时检测到,并调用当前安装的 约束处理函数,而不在 ptr 指向的对象中存储任何内容
    • strmaxdelimptr 是空指针。
    • 对于序列中的后续调用,*ptr 是空指针。
    • *strmax 大于 RSIZE_MAX
    • 找到的标记的末尾未出现在搜索目标的前 *s1max 个字符内。
如果 str 指向缺少空字符的字符数组,并且 strmax 指向的值大于该字符数组的大小,则行为未定义。
与所有边界检查函数一样,仅当实现定义了 __STDC_LIB_EXT1__ 并且用户在包含 <string.h> 之前将 __STDC_WANT_LIB_EXT1__ 定义为整数常量 1 时,才能保证 strtok_s 可用。
  1. 在使用不同的分隔符字符串的后续调用中,仍然可以形成标记。
  2. 在后续调用中无法再形成标记。

目录

[编辑] 参数

str - 指向要标记化的空终止字节字符串的指针
delim - 指向标识分隔符的空终止字节字符串的指针
strmax - 指向最初保存 str 大小的对象的指针:strtok_s 存储剩余要检查的字符数
ptr - 指向 char* 类型的对象的指针,strtok_s 使用它来存储其内部状态

[编辑] 返回值

1) 返回指向下一个标记的第一个字符的指针,如果没有标记,则返回空指针。
2) 返回指向下一个标记的第一个字符的指针,如果没有标记或存在运行时约束冲突,则返回空指针。

[编辑] 注意

此函数是破坏性的:它在字符串 str 的元素中写入 '\0' 字符。 特别是,字符串字面量不能用作 strtok 的第一个参数。

每次调用 strtok 都会修改静态变量:不是线程安全的。

与大多数其他标记器不同,strtok 中的分隔符对于每个后续标记可能不同,甚至可能取决于先前标记的内容。

strtok_s 函数与 POSIX strtok_r 函数的不同之处在于,它防止存储在被标记化的字符串之外,并通过检查运行时约束。 Microsoft CRT strtok_s 签名与此 POSIX strtok_r 定义匹配,而不是 C11 strtok_s

[编辑] 示例

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    char input[] = "A bird came down the walk";
    printf("Parsing the input string '%s'\n", input);
    char* token = strtok(input, " ");
    while (token)
    {
        puts(token);
        token = strtok(NULL, " ");
    }
 
    printf("Contents of the input string now: '");
    for (size_t n = 0; n < sizeof input; ++n)
        input[n] ? putchar(input[n]) : fputs("\\0", stdout);
    puts("'");
 
#ifdef __STDC_LIB_EXT1__
    char str[] = "A bird came down the walk";
    rsize_t strmax = sizeof str;
    const char* delim = " ";
    char* next_token;
    printf("Parsing the input string '%s'\n", str);
    token = strtok_s(str, &strmax, delim, &next_token);
    while (token)
    {
        puts(token);
        token = strtok_s(NULL, &strmax, delim, &next_token);
    }
 
    printf("Contents of the input string now: '");
    for (size_t n = 0; n < sizeof str; ++n)
        str[n] ? putchar(str[n]) : fputs("\\0", stdout);
    puts("'");
#endif
}

可能的输出

Parsing the input string 'A bird came down the walk'
A
bird
came
down
the
walk
Contents of the input string now: 'A\0bird\0came\0down\0the\0walk\0'
Parsing the input string 'A bird came down the walk'
A
bird
came
down
the
walk
Contents of the input string now: 'A\0bird\0came\0down\0the\0walk\0'

[编辑] 参考文献

  • C23 标准 (ISO/IEC 9899:2024)
  • 7.24.5.8 strtok 函数 (p: TBD)
  • K.3.7.3.1 strtok_s 函数 (p: TBD)
  • C17 标准 (ISO/IEC 9899:2018)
  • 7.24.5.8 strtok 函数 (p: TBD)
  • K.3.7.3.1 strtok_s 函数 (p: TBD)
  • C11 标准 (ISO/IEC 9899:2011)
  • 7.24.5.8 strtok 函数 (p: 369-370)
  • K.3.7.3.1 strtok_s 函数 (p: 620-621)
  • C99 标准 (ISO/IEC 9899:1999)
  • 7.21.5.8 strtok 函数 (p: 332-333)
  • C89/C90 标准 (ISO/IEC 9899:1990)
  • 4.11.5.8 strtok 函数

[编辑] 参见

在一个字符串中查找另一个字符串中任何字符的第一个位置
(函数) [编辑]
返回由以下字符组成的最大初始段的长度
仅由在另一个字节字符串中未找到的字符组成
(函数) [编辑]
返回由以下字符组成的最大初始段的长度
仅由在另一个字节字符串中找到的字符组成
(函数) [编辑]
(C95)(C11)
在宽字符串中查找下一个标记
(函数) [编辑]
C++ 文档 关于 strtok