Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ strtok()-为什么必须传递空指针才能获取字符串中的下一个标记?_C++_C_String_Pointers_Strtok - Fatal编程技术网

C++ strtok()-为什么必须传递空指针才能获取字符串中的下一个标记?

C++ strtok()-为什么必须传递空指针才能获取字符串中的下一个标记?,c++,c,string,pointers,strtok,C++,C,String,Pointers,Strtok,这是strtok()的解释 #包括 char*strtok(char*s1, 常量字符*s2)* 对strtok()的第一个调用返回指向 s1指向的字符串。对strtok()的后续调用必须传递NULL 指针作为第一个参数,以便在 绳子 但我不知道,为什么必须传递NULL指针才能获得字符串中的下一个标记。我搜索了大约15分钟,但在互联网上没有找到解释。如果传递非空值,则要求它开始标记不同的字符串 如果传递空值,则要求继续标记与以前相同的内容。strtok()使用静态变量将一些数据保存在自身内部。

这是strtok()的解释

#包括
char*strtok(char*s1,
常量字符*s2)*
对strtok()的第一个调用返回指向 s1指向的字符串。对strtok()的后续调用必须传递NULL 指针作为第一个参数,以便在 绳子


但我不知道,为什么必须传递NULL指针才能获得字符串中的下一个标记。我搜索了大约15分钟,但在互联网上没有找到解释。

如果传递非空值,则要求它开始标记不同的字符串

如果传递空值,则要求继续标记与以前相同的内容。

strtok()
使用静态变量将一些数据保存在自身内部。这样,
strtok()
就可以从上次调用时中断的位置继续搜索。要向strtok()发出持续搜索同一字符串的信号,请传递一个
NULL
指针作为其第一个参数
strtok()
检查第一个参数是否为
NULL
,如果是,则使用当前存储的数据。如果第一个参数不为null,则将其视为新的搜索,并重置所有内部数据

也许您能做的最好的事情就是搜索
strok()
函数的实际实现。我发现了一个足够小的参数,可以在这里发布,因此您可以了解如何处理此空参数:

/* Copyright (c) Microsoft Corporation. All rights reserved. */

#include <string.h>

/* ISO/IEC 9899 7.11.5.8 strtok. DEPRECATED.
 * Split string into tokens, and return one at a time while retaining state
 * internally.
 *
 * WARNING: Only one set of state is held and this means that the
 * WARNING: function is not thread-safe nor safe for multiple uses within
 * WARNING: one thread.
 *
 * NOTE: No library may call this function.
 */

char * __cdecl strtok(char *s1, const char *delimit)
{
    static char *lastToken = NULL; /* UNSAFE SHARED STATE! */
    char *tmp;

    /* Skip leading delimiters if new string. */
    if ( s1 == NULL ) {
        s1 = lastToken;
        if (s1 == NULL)         /* End of story? */
            return NULL;
    } else {
        s1 += strspn(s1, delimit);
    }

    /* Find end of segment */
    tmp = strpbrk(s1, delimit);
    if (tmp) {
        /* Found another delimiter, split string and save state. */
        *tmp = '\0';
        lastToken = tmp + 1;
    } else {
        /* Last segment, remember that. */
        lastToken = NULL;
    }

    return s1;
}
/*版权所有(c)微软公司。版权所有*/
#包括
/*ISO/IEC 9899 7.11.5.8标准。不赞成。
*将字符串拆分为标记,并在保留状态的同时一次返回一个标记
*内部。
*

*警告:仅保留一组状态,这意味着 *警告:函数不是线程安全的,也不能在中多次使用 *警告:一个线程。 * *注意:任何库都不能调用此函数。 */ char*\uuu cdecl strtok(char*s1,const char*divident) { 静态char*lastToken=NULL;/*不安全的共享状态*/ char*tmp; /*如果是新字符串,则跳过前导分隔符*/ 如果(s1==NULL){ s1=最后一个令牌; 如果(s1==NULL)/*故事结束*/ 返回NULL; }否则{ s1+=strspn(s1,定界); } /*查找段的结尾*/ tmp=strpbrk(s1,定界); 如果(tmp){ /*找到另一个分隔符,拆分字符串并保存状态*/ *tmp='\0'; lastToken=tmp+1; }否则{ /*最后一段,记住这一点*/ lastToken=NULL; } 返回s1; }
如果代码没有通过
NULL
,那么代码应该通过什么来继续标记相同的字符串?我想这只是为了让您可以选择一次不标记整个字符串,而不跟踪下一个标记的起始位置。如果这是C++设计的,那么它很可能是不同的。你在搜索中没有看到它?Beaus,这是它40年前设计的方式。糟糕。单线程和单用途(不可嵌套),而不是提供上下文对象。我搜索的单词是“non-re-entrant”。但是,strtok怎么知道它是同一个字符串?现在传递NULL,但这不是字符串的地址。@ezph1,它一次只处理一个字符串,并保持内部状态,这会导致各种问题。非常感谢,现在我明白了!*警告:只保留一组状态,这意味着*WARNING:函数不是线程安全的,在*WARNING:一个线程内多次使用也不安全。这意味着什么?@MinhTran这意味着这个函数不应该在多线程调用中使用,因为静态变量可能会被其他线程更改。请参阅
/*不安全共享状态*/
/* Copyright (c) Microsoft Corporation. All rights reserved. */

#include <string.h>

/* ISO/IEC 9899 7.11.5.8 strtok. DEPRECATED.
 * Split string into tokens, and return one at a time while retaining state
 * internally.
 *
 * WARNING: Only one set of state is held and this means that the
 * WARNING: function is not thread-safe nor safe for multiple uses within
 * WARNING: one thread.
 *
 * NOTE: No library may call this function.
 */

char * __cdecl strtok(char *s1, const char *delimit)
{
    static char *lastToken = NULL; /* UNSAFE SHARED STATE! */
    char *tmp;

    /* Skip leading delimiters if new string. */
    if ( s1 == NULL ) {
        s1 = lastToken;
        if (s1 == NULL)         /* End of story? */
            return NULL;
    } else {
        s1 += strspn(s1, delimit);
    }

    /* Find end of segment */
    tmp = strpbrk(s1, delimit);
    if (tmp) {
        /* Found another delimiter, split string and save state. */
        *tmp = '\0';
        lastToken = tmp + 1;
    } else {
        /* Last segment, remember that. */
        lastToken = NULL;
    }

    return s1;
}