STRTOK - Linux手册页

时间:2019-08-20 18:01:26  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

strtok,strtok_r-从字符串中提取令牌

语法

#include <string.h>

char *strtok(char *str, const char *delim);

char *strtok_r(char *str, const char *delim, char **saveptr);

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

strtok_r():_POSIX_C_SOURCE
|| / * Glibc版本

说明

strtok()函数将字符串分成零个或多个非空标记的序列。在第一次调用strtok()时,应在str中指定要解析的字符串。在每个随后的应解析相同字符串的调用中,str必须为NULL。

delim参数指定一组字节,这些字节定界已分析字符串中的标记。调用方可以在解析同一字符串的连续调用中以delim指定不同的字符串。

每次对strtok()的调用都会返回一个指向以空值结尾的字符串的指针,该字符串包含下一个标记。该字符串不包含定界字节。如果找不到更多令牌,则strtok()返回NULL。

在同一字符串上操作strtok()的一系列调用将维护一个指针,该指针确定从其开始搜索下一个标记的点。首次调用strtok()会将此指针设置为指向字符串的第一个字节。通过向前扫描str中的下一个非定界字节来确定下一个标记的开始。如果找到了这样的字节,则将其作为下一个令牌的开始。如果找不到这样的字节,则不再有令牌,并且strtok()返回NULL。 (因此,一个空字符串或仅包含定界符的字符串将导致strtok()在首次调用时返回NULL。)

通过向前扫描直到找到下一个分隔符字节或遇到终止空字节(aq \ 0aq),才能找到每个令牌的末尾。如果找到定界符字节,则将其用空字节覆盖以终止当前令牌,并且strtok()保存指向下一个字节的指针;搜索下一个令牌时,该指针将用作起点。在这种情况下,strtok()返回一个指向找到的令牌开始的指针。

根据上面的描述,可以得出以下结论:已分析字符串中两个或多个连续定界符字节的序列被视为单个定界符,并且忽略字符串开头或结尾处的定界符字节。换句话说,strtok()返回的令牌始终是非空字符串。因此,例如,给定字符串" aaa ;; bbb",对strtok()的连续调用将指定分隔符字符串";",将返回字符串" aaa"和" bbb",然后返回空指针。

strtok_r()函数是strtok()的可重入版本。 saveptr参数是一个指向char *变量的指针,该变量由strtok_r()在内部使用,以维护解析同一字符串的连续调用之间的上下文。

在第一次调用strtok_r()时,str应该指向要解析的字符串,并且* saveptr的值将被忽略(但请参见NOTES)。在后续调用中,str应该为NULL,并且自上次调用以来,saveptr(及其指向的缓冲区)应该保持不变。

可以使用对strtok_r()的调用序列(指定不同的saveptr参数)同时解析不同的字符串。

返回值

strtok()和strtok_r()函数返回指向下一个标记的指针,如果没有更多标记,则返回NULL。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
strtok()Thread safetyMT-Unsafe race:strtok
strtok_r()Thread safetyMT-Safe

遵循规范

strtok()
POSIX.1-2001,POSIX.1-2008,C89,C99,SVr4、4.3BSD。
strtok_r()
POSIX.1-2001,POSIX.1-2008。

备注

在某些实现中,在第一次用于解析str的strtok_r()上,* saveptr必须为NULL。

BUGS

使用这些功能时要小心。如果确实使用它们,请注意:

*
这些函数修改其第一个参数。
*
这些函数不能在常量字符串上使用。
*
分隔字节的标识丢失。
*
strtok()函数在解析时使用静态缓冲区,因此它不是线程安全的。如果这很重要,请使用strtok_r()。

示例

下面的程序使用嵌套循环,该循环使用strtok_r()将字符串分为两级标记层次结构。第一个命令行参数指定要分析的字符串。第二个参数指定用于将字符串分成"主要"标记的定界符字节。第三个参数指定用于将"主要"标记分成子标记的定界符字节。

该程序产生的输出示例如下:

$ ./a.out aqa/bbb///cc;xxx:yyy:aq aq:;aq aq/aq
1: a/bbb///cc
         --> a
         --> bbb
         --> cc
2: xxx
         --> xxx
3: yyy
         --> yyy

Program source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char *argv[])
{
    char *str1, *str2, *token, *subtoken;
    char *saveptr1, *saveptr2;
    int j;

    if (argc != 4) {
        fprintf(stderr, "Usage: %s string delim subdelim\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }

    for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
        token = strtok_r(str1, argv[2], &saveptr1);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);

        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok_r(str2, argv[3], &saveptr2);
            if (subtoken == NULL)
                break;
            printf("	 --> %s\n", subtoken);
        }
    }

    exit(EXIT_SUCCESS);
}

可以在getaddrinfo_a(3)中找到使用strtok()的另一个示例程序。

另外参见

index(3),memchr(3),rindex(3),strchr(3),string(3),strpbrk(3),strsep(3),strspn(3),strstr(3),wcstok(3)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/