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
不是空指针,则该调用被视为对此特定字符串的第一次strtok
调用。该函数搜索第一个*不*包含在delim
中的字符。
- 如果未找到此类字符,则
str
中根本没有任何标记,并且该函数返回一个空指针。 - 如果找到了这样的字符,则它是*标记的开头*。然后,该函数从该点开始搜索第一个*包含*在
delim
中的字符。
- 如果未找到此类字符,则
str
只有一个标记,并且对strtok
的未来调用将返回一个空指针 - 如果找到了这样的字符,则将其*替换*为空字符 '\0',并将指向下一个字符的指针存储在静态位置,以便后续调用使用。
- 如果未找到此类字符,则
- 然后,该函数返回指向标记开头的指针
- 如果未找到此类字符,则
- 如果
str
是一个空指针,则该调用被视为对strtok
的后续调用:该函数从上一次调用的位置继续执行。其行为与传递先前存储的指针作为 str 相同。
- 如果
如果
str
或 delim
不是指向以空字符结尾的字节字符串的指针,则行为未定义。2) 与 (1) 相同,不同之处在于,在每一步,都会将
str
中剩余的字符数写入 *strmax,并将分词器的内部状态写入 *ptr。重复调用(使用空 str
)必须传递 strmax
和 ptr
,并使用上一次调用存储的值。此外,还会在运行时检测以下错误,并调用当前安装的 约束处理函数,而不会在 ptr
指向的对象中存储任何内容-
strmax
、delim
或ptr
是空指针 - 在非初始调用(使用空
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)