strtok, strtok_s

< 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 指向的值大于该字符数组长度,则行为未定义。
同所有边界检查函数, strtok_s 仅若实现定义 __STDC_LIB_EXT1__ 且用户在包含 string.h 前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。

参数

str - 指向要记号化的空终止字节字符串的指针
delim - 指向标识分隔符的空终止字节字符串的指针
strmax - 指向最初保有 str 长度的对象指针: strtok_s 存储留待检验的字符数
ptr - 指向 char* 类型对象的指针, strtok_s 以之存储其内部状态

返回值

返回指向下个记号起始的指针,或若无更多记号则返回空指针。

注解

此函数是破坏性的:它写入 '\0' 字符到字符串 str 的元素。特别是,不能以字符串字面量为 strtok 的首参数。

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

不同于大多数其他记号化器, strtok 中的分隔符能对于后继记号不同,而且甚至能依赖于先前记号的内容。

strtok_s 函数异于 POSIX strtok_r 函数,前者通过在被记号化的字符串外部存储,和检查运行时制约来防护。

示例

#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 standard (ISO/IEC 9899:2011):
  • 7.24.5.8 The strtok function (p: 369-370)
  • K.3.7.3.1 The strtok_s function (p: 620-621)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.21.5.8 The strtok function (p: 332-333)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 4.11.5.8 The strtok function

参阅

查找一个字符串中的任意一个字符在另一个字符串中的首个位置
(函数)
返回另一个字符串所不具有的字符分割的最大起始段长度
(函数)
返回由另一个字符串中的字符分割的最大起始段长度
(函数)
(C95)(C11)
查找宽字符串中的下一个记号
(函数)