strtok和strep在C中有什么区别

strtok和strep在C中有什么区别,c,strtok,strsep,C,Strtok,Strsep,有人能给我解释一下strtok()和strep()之间有什么区别吗? 它们的优点和缺点是什么? 为什么我要选择一个而不是另一个。摘自GNU C库手册-: strep和strtok_r之间的一个区别是,如果输入字符串在一行中包含来自分隔符的多个字符,则strep将为来自分隔符的每对字符返回一个空字符串。这意味着程序在处理空字符串之前,通常应该测试是否返回空字符串 和之间的一个主要区别是,strtok()是标准化的(由C标准,因此也是由POSIX),但不是标准化的(由C或POSIX;它在GNU C库

有人能给我解释一下strtok()和strep()之间有什么区别吗? 它们的优点和缺点是什么?
为什么我要选择一个而不是另一个。

摘自GNU C库手册-:

strep
strtok_r
之间的一个区别是,如果输入字符串在一行中包含来自分隔符的多个字符,则
strep
将为来自分隔符的每对字符返回一个空字符串。这意味着程序在处理空字符串之前,通常应该测试是否返回空字符串


和之间的一个主要区别是,
strtok()
是标准化的(由C标准,因此也是由POSIX),但不是标准化的(由C或POSIX;它在GNU C库中可用,并且源于BSD)。因此,可移植代码更可能使用
strtok()
而不是
strep()

另一个区别是,对不同字符串上的
strep()
函数的调用可以交错,而使用
strtok()
(尽管可以使用
strtok_r()
)来实现这一点)。因此,在库中使用
strep()
不会意外中断其他代码,而在库函数中使用
strtok()
必须记录在案,因为同时使用
strtok()
的其他代码无法调用库函数

strep()
at的手册页上写着:

strsep()函数是作为strtok(3)的替代品引入的,因为后者不能处理空字段

因此,另一个主要区别是他在回答中强调的区别
strtok()
允许在单个令牌之间使用多个分隔符,而
strep()
要求令牌之间使用单个分隔符,并将相邻分隔符解释为空令牌

strep()
strtok()
都可以修改它们的输入字符串,并且都不允许您识别标记令牌结尾的分隔符字符(因为两者都在令牌结尾后的分隔符上写入NUL
'\0'

什么时候使用它们?
  • 如果您想要空令牌,而不是在令牌之间允许多个分隔符,并且不介意可移植性,则可以使用
    strep()
  • 如果希望在令牌之间允许多个分隔符,而不希望使用空令牌(并且POSIX对您来说是足够可移植的),则可以使用
    strtok_r()
  • 只有当有人威胁你的生命时,如果你不这样做,你才会使用strtok()。而你只会使用它足够长的时间,让你摆脱生命威胁的情况;然后,您将再次放弃对它的所有使用。它有毒;不要使用它。编写自己的
    strtok\u r()
    strep()
    比使用
    strtok()
    更好
为什么strtok()有毒? 如果在库函数中使用
strtok()
函数,则该函数是有毒的。如果库函数使用strtok(),则必须清楚地记录它

那是因为:

  • 如果任何调用函数正在使用
    strtok()
    并调用同样使用
    strtok()
    的函数,则会中断调用函数
  • 如果您的函数调用任何调用
    strtok()
    的函数,则会中断函数对
    strtok()
    的使用
  • 如果您的程序是多线程的,则在任何给定时间,最多有一个线程可以在一系列调用中使用strok()
  • 此问题的根源是调用之间的已保存状态,它允许
    strtok()
    在停止时继续。除了“请勿使用
    strtok()
    ”之外,没有其他明智的方法来解决此问题

    • 如果可用,可以使用
      strep()
    • 如果POSIX可用,您可以使用它
    • 如果有微软的,你可以使用它
    • 名义上,您可以使用ISO/IEC 9899:2011附录K.3.7.3.1函数
      strtok__()
    BSD
    strep()

    POSIX
    strtok_r()

    Microsoft
    strtok\u s()

    附件K
    strtok_s()


    请注意,这有4个参数,而不是像
    strtok()

    上的其他两个变量那样有3个。
    strtok()
    strep()
    的第一个区别是它们处理输入字符串中连续分隔符字符的方式

    strtok()
    处理的连续分隔符字符:

    在输出中,您可以依次看到令牌
    “bbb”
    “ccc”
    strtok()
    不指示连续分隔符的出现。另外,
    strtok()
    修改输入字符串

    strep()处理的连续分隔符字符

    输出:

    # ./example1_strtok
    Original String: aaa-bbb --ccc-ddd
    aaa
    bbb
    ccc
    ddd
    Original String: aaa
    
    # ./example1_strsep
    Original String: aaa-bbb --ccc-ddd
    aaa
    bbb
    <empty>             <==============
    <empty>             <==============
    ccc
    ddd
    ptr1 is NULL
    Original String: aaa
    
    # ./example2_strtok
    Original String: aaa --bbb-ccc
    aaa
    Original String: ttt -vvvv
    ttt
    vvvv
    another_function_callng_strtok: I am done.
    
    # ./example2_strsep
    Original String: aaa --bbb-ccc
    aaa
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    <empty>
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    <empty>
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    bbb
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    ccc
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    
    函数
    function\u callng\u strtok()
    只打印令牌
    “aaa”
    ,不打印输入字符串的其余令牌,因为它调用了
    另一个函数\u callng\u strtok()
    ,后者反过来调用
    strtok()
    ,并设置
    strtok()的静态指针
    NULL
    提取完所有令牌后。控件返回到
    函数调用
    循环时,
    strtok()
    由于指向
    NULL
    的静态指针而返回
    NULL
    ,从而使循环条件
    false
    并退出循环

    当另一个
    strep()
    未完成时调用
    strep()

    #include <stdio.h>
    #include <string.h>
    
    void another_function_callng_strtok(void)
    {
        char str[] ="ttt -vvvv";
        char* delims = " -";
        char* token;
    
        printf ("Original String: %s\n", str);
        token = strtok (str, delims);
        while (token != NULL) {
            printf ("%s\n", token);
            token = strtok (NULL, delims);
        }
        printf ("another_function_callng_strtok: I am done.\n");
    }
    
    void function_callng_strtok ()
    {
        char str[] ="aaa --bbb-ccc";
        char* delims = " -";
        char* token;
    
        printf ("Original String: %s\n", str);
        token = strtok (str, delims);
        while (token != NULL)
        {
            printf ("%s\n",token);
            another_function_callng_strtok();
            token = strtok (NULL, delims);
        }
    }
    
    int main(void) {
        function_callng_strtok();
        return 0;
    }
    
    #include <stdio.h>
    #include <string.h>
    
    void another_function_callng_strsep(void)
    {
        char str[] ="ttt -vvvv";
        const char* delims = " -";
        char* token;
        char* ptr = str;
    
        printf ("Original String: %s\n", str);
        while ((token = strsep(&ptr, delims)) != NULL) {
            if (*token == '\0') {
                token = "<empty>";
            }
            printf("%s\n", token);
        }
        printf ("another_function_callng_strsep: I am done.\n");
    }
    
    void function_callng_strsep ()
    {
        char str[] ="aaa --bbb-ccc";
        const char* delims = " -";
        char* token;
        char* ptr = str;
    
        printf ("Original String: %s\n", str);
        while ((token = strsep(&ptr, delims)) != NULL) {
            if (*token == '\0') {
                token = "<empty>";
            }
            printf("%s\n", token);
            another_function_callng_strsep();
        }
    }
    
    int main(void) {
        function_callng_strsep();
        return 0;
    }
    
    #包括
    #包括
    void另一个函数调用strep(void)
    {
    字符str[]=“ttt-VVV”;
    骗局
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void) {
        const char* teststr = "aaa-bbb --ccc-ddd"; //Contiguous delimiters between bbb and ccc sub-string
        const char* delims = " -";  // delimiters - space and hyphen character
        char* token;
        char* ptr1;
        char* ptr = strdup(teststr);
    
        if (ptr == NULL) {
            fprintf(stderr, "strdup failed");
            exit(EXIT_FAILURE);
        }
    
        ptr1 = ptr;
    
        printf ("Original String: %s\n", ptr);
        while ((token = strsep(&ptr1, delims)) != NULL) {
            if (*token == '\0') {
                token = "<empty>";
            }
            printf("%s\n", token);
        }
    
        if (ptr1 == NULL) // This is just to show that the strsep() modifies the pointer passed to it
            printf ("ptr1 is NULL\n");
        printf ("Original String: %s\n", ptr);
        free (ptr);
        return 0;
    }
    
    # ./example1_strsep
    Original String: aaa-bbb --ccc-ddd
    aaa
    bbb
    <empty>             <==============
    <empty>             <==============
    ccc
    ddd
    ptr1 is NULL
    Original String: aaa
    
    #include <stdio.h>
    #include <string.h>
    
    void another_function_callng_strtok(void)
    {
        char str[] ="ttt -vvvv";
        char* delims = " -";
        char* token;
    
        printf ("Original String: %s\n", str);
        token = strtok (str, delims);
        while (token != NULL) {
            printf ("%s\n", token);
            token = strtok (NULL, delims);
        }
        printf ("another_function_callng_strtok: I am done.\n");
    }
    
    void function_callng_strtok ()
    {
        char str[] ="aaa --bbb-ccc";
        char* delims = " -";
        char* token;
    
        printf ("Original String: %s\n", str);
        token = strtok (str, delims);
        while (token != NULL)
        {
            printf ("%s\n",token);
            another_function_callng_strtok();
            token = strtok (NULL, delims);
        }
    }
    
    int main(void) {
        function_callng_strtok();
        return 0;
    }
    
    # ./example2_strtok
    Original String: aaa --bbb-ccc
    aaa
    Original String: ttt -vvvv
    ttt
    vvvv
    another_function_callng_strtok: I am done.
    
    #include <stdio.h>
    #include <string.h>
    
    void another_function_callng_strsep(void)
    {
        char str[] ="ttt -vvvv";
        const char* delims = " -";
        char* token;
        char* ptr = str;
    
        printf ("Original String: %s\n", str);
        while ((token = strsep(&ptr, delims)) != NULL) {
            if (*token == '\0') {
                token = "<empty>";
            }
            printf("%s\n", token);
        }
        printf ("another_function_callng_strsep: I am done.\n");
    }
    
    void function_callng_strsep ()
    {
        char str[] ="aaa --bbb-ccc";
        const char* delims = " -";
        char* token;
        char* ptr = str;
    
        printf ("Original String: %s\n", str);
        while ((token = strsep(&ptr, delims)) != NULL) {
            if (*token == '\0') {
                token = "<empty>";
            }
            printf("%s\n", token);
            another_function_callng_strsep();
        }
    }
    
    int main(void) {
        function_callng_strsep();
        return 0;
    }
    
    # ./example2_strsep
    Original String: aaa --bbb-ccc
    aaa
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    <empty>
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    <empty>
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    bbb
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.
    ccc
    Original String: ttt -vvvv
    ttt
    <empty>
    vvvv
    another_function_callng_strsep: I am done.