【问题标题】:strtok() - Why you have to pass the NULL pointer in order to get the next token in the string?strtok() - 为什么必须传递 NULL 指针才能获得字符串中的下一个标记?
【发布时间】:2015-06-20 17:27:38
【问题描述】:

这是strtok()的解释。

#include <string.h>
char* strtok( char* s1, 
              const char* s2 );*

第一次调用 strtok() 返回指向第一个标记的指针 s1 指向的字符串。对 strtok() 的后续调用必须传递一个 NULL 指针作为第一个参数,以获取下一个标记 字符串。

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

【问题讨论】:

  • 如果代码没有通过NULL,代码应该通过什么来继续标记相同的字符串?
  • 我想这只是为了让您可以选择不立即标记整个字符串,而无需自己跟踪从哪里开始下一个标记。如果现在这是用 C++ 设计的,那很可能会有所不同。
  • 您没有在搜索中看到cplusplus.com/reference/cstring/strtok
  • 因为这是 40 年前的设计方式。不良。单线程和单次使用(不可嵌套),而不是提供上下文对象。
  • 我搜索的词是“non-re entrant”。

标签: c++ c string pointers strtok


【解决方案1】:

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

也许您能做的最好的事情就是搜索strtok() 函数的实际实现。我找到了一个足够小的,可以在这里发布,所以你会知道如何处理这个 NULL 参数:

/* 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;
}

【讨论】:

  • 非常感谢,现在我明白了!
  • * WARNING: 只有一组状态被保存,这意味着 * WARNING: 函数不是线程安全的,也不能安全地在 * WARNING: 一个线程中多次使用。这是什么意思?
  • @MinhTran 这意味着这个函数不应该在多线程调用中使用,因为静态变量可能被其他线程更改。见/* UNSAFE SHARED STATE! */
【解决方案2】:

如果你传递一个非 NULL 值,你是在要求它开始标记不同的字符串。

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

【讨论】:

  • 但是,strtok 怎么知道它是同一个字符串?现在你传递 NULL,但这不是字符串的地址。
  • @ezph1,它一次只处理一个字符串并保持内部状态,这会导致各种问题。
猜你喜欢
  • 2016-06-02
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多