命名空间
变体
操作

strtok, strtok_s

来自 cppreference.com
< 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)str 指向的以空字符结尾的字节字符串中查找下一个标记。分隔符由 delim 指向的以空字符结尾的字节字符串标识。
此函数设计为可多次调用,以从同一个字符串中获取连续的标记。
  • 如果 str 不是空指针,则该调用被视为对此特定字符串的第一次 strtok 调用。该函数搜索第一个*不*包含在 delim 中的字符。
  • 如果未找到此类字符,则 str 中根本没有任何标记,并且该函数返回一个空指针。
  • 如果找到了这样的字符,则它是*标记的开头*。然后,该函数从该点开始搜索第一个*包含*在 delim 中的字符。
  • 如果未找到此类字符,则 str 只有一个标记,并且对 strtok 的未来调用将返回一个空指针
  • 如果找到了这样的字符,则将其*替换*为空字符 '\0',并将指向下一个字符的指针存储在静态位置,以便后续调用使用。
  • 然后,该函数返回指向标记开头的指针
  • 如果 str 是一个空指针,则该调用被视为对 strtok 的后续调用:该函数从上一次调用的位置继续执行。其行为与传递先前存储的指针作为 str 相同。
如果 strdelim 不是指向以空字符结尾的字节字符串的指针,则行为未定义。
2)(1) 相同,不同之处在于,在每一步,都会将 str 中剩余的字符数写入 *strmax,并将分词器的内部状态写入 *ptr。重复调用(使用空 str)必须传递 strmaxptr,并使用上一次调用存储的值。此外,还会在运行时检测以下错误,并调用当前安装的 约束处理函数,而不会在 ptr 指向的对象中存储任何内容
  • strmaxdelimptr 是空指针
  • 在非初始调用(使用空 str)中,*ptr 是空指针
  • 在第一次调用中,*strmax 为零或大于 RSIZE_MAX
  • 搜索标记结尾到达源字符串的结尾(由 *strmax 的初始值测量)时,没有遇到空终止符
如果 str 指向一个缺少空字符的字符数组,并且 strmax 指向的值大于该字符数组的大小,则行为未定义。
与所有边界检查函数一样,只有当实现定义了 __STDC_LIB_EXT1__ 并且用户在包含 <string.h> 之前将 __STDC_WANT_LIB_EXT1__ 定义为整型常量 1 时,才能保证 strtok_s 可用。

目录

[编辑] 参数

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

[编辑] 返回值

返回指向下一个标记开头的指针,如果没有更多标记,则返回空指针。

[编辑] 注意

此函数具有破坏性:它会在字符串 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 <string.h>
#include <stdio.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'

[编辑] 参考

  • 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