strtok, strtok_s
来自cppreference.com
定义于头文件 <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 != NULL ,则调用被当做
strtok
对此特定字符串的首次调用。函数搜索首个不含于delim
的字符。
- 若找不到这种字符,则
str
中完全没有记号,而函数返回空指针。 - 若找到这种字符,则它是记号的起始。然后函数从
delim
所含的首个字符的该点搜索。
- 若找不到这种字符,则
str
只有一个记号,而将来对strtok
的调用将返回空指针 - 若找到这种字符,则用空字符 '\0' 替换它,并将指向下个字符的指针存储于静态位置,以为后继调用所用。
- 若找不到这种字符,则
- 然后函数返回指向记号起始的指针
- 若找不到这种字符,则
- 若 str == NULL ,则将调用当做对
strtok
的后继调用,函数从先前调用中它剩下的位置开始。行为如同将先前存储的指针作为 str 传递。
- 若 str != NULL ,则调用被当做
若
str
或 delim
不是指向空终止字节字符串的指针,则行为未定义。2) 同 (1) ,除了在每步时,写入
str
中留待查看的字符数到 *strmax ,并写入记号化器的初始状态到 *ptr 。重复的调用(以空 str
)必须传递先前的调用用以存储值的 strmax
和 ptr
。另外,在运行时检测下列错误,并调用当前安装的制约处理函数:
-
strmax
、delim
或ptr
为空指针 - 非首次调用(以
str
)时,*ptr
为空指针 - 首次调用时, *strmax 为零或大于 RSIZE_MAX
- 对记号尾的搜索抵达源字符串的结尾(由 *strmax 的初值测量)而未遇到空终止符
-
同时不存储任何内容于
ptr
所指向的对象 若
str
指向的字符数组缺少空终止符,而 strmax
指向的值大于该字符数组长度,则行为未定义。
- 同所有边界检查函数,
strtok_s
仅若实现定义了 __STDC_LIB_EXT1__ ,且用户在包含string.h
前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。
参数
str | - | 指向要记号化的空终止字节字符串的指针 |
delim | - | 指向标识分隔符的空终止字节字符串的指针 |
strmax | - | 指向最初保有 str 长度的对象指针: strtok_s 存储留待检验的字符数
|
ptr | - | 指向 char* 类型对象的指针, strtok_s 以之存储其内部状态 |
返回值
返回指向下个记号起始的指针,或若无更多记号则返回 NULL 。
注意
此函数是破坏性的:它写入 '\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) |
查找宽字符串中的下一个记号 (函数) |