strtok, strtok_s
来自 cppreference.cn
定义于头文件 <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 所指向的分隔符字符串中的字符,分隔符字符串可以在每次调用中不同。
如果 str 或 delim 不是指向以空字符结尾的字节字符串的指针,则行为未定义。
2) 与 (1) 相同,但有以下不同之处
- 在每次调用中,将 str 中剩余的字符数写入 *strmax,并将标记器的内部状态写入 *ptr。
- 序列中的后续调用必须传入具有上一次调用存储的值的 strmax 和 ptr。
- 以下错误会在运行时检测到,并调用当前安装的约束处理函数,而不将任何内容存储到 ptr 所指向的对象中
- strmax、delim 或 ptr 为空指针。
- 对于序列中的后续调用,*ptr 为空指针。
- *strmax 大于 RSIZE_MAX。
- 找到的标记末尾未出现在搜索目标的前 *s1max 个字符内。
如果 str 指向的字符数组缺少空字符,且 strmax 指向的值大于该字符数组的大小,则行为未定义。
与所有边界检查函数一样,只有当实现定义了 __STDC_LIB_EXT1__ 并且用户在包含 <string.h> 之前将 __STDC_WANT_LIB_EXT1__ 定义为整数常量 1 时,才保证
strtok_s
可用。目录 |
[编辑] 参数
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
|