这个为任何环境字符串创建链接列表的函数应该如何工作?

How is this function that creates a linked list for any environment string supposed to work?

代码如下:

typedef struct Node
{
    char *str;
    struct Node *next;

} Node;

Node *_getdir(char *path, char **pathCopy)
{
    char *token = NULL;
    Node *head;
    Node *pathNode;


if (path == NULL)
    return (NULL);

*pathCopy = strdup(path); 

head = NULL;
pathNode = malloc(sizeof(Node));
if (pathNode == NULL)
    return (NULL);

token = strtok(*pathCopy,  ":");
pathNode->str = token;
pathNode->next = head;
head = pathNode;
while (token != NULL)
{
    token = strtok(NULL, ":");
    if (token == NULL) 
        break;
    pathNode = malloc(sizeof(Node));
    if (pathNode == NULL)
        return (NULL);
    pathNode->str = token;
    pathNode->next = head;
    head = pathNode;
}
return (head);

}
path = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
char *pathCopy = NULL;
pathDirs = _getdir(path, pathCopy);

我的困惑从 pathNode = malloc(sizeof(Node)) 开始,到 return (head);

结束

首先,我不明白为什么这个函数要分配一个名为“Node”的类型变量的大小,并将该信息存储在一个名为pathNode的变量中,并且恰到好处之后有一个 if statement 要执行以防 pathNode 是 NULL 值,我的意思是,如果“节点”类型变量是固定的(至少在最初)?

其次,我了解到strtok函数是通过分隔符来分割字符串的,在本例中是:。我还知道箭头运算符 -> 用于访问 Structures.

中的元素

但是,接下来的代码行是 pathNode->str = token;pathNode->next = head;,它们类似于某种 变量声明反转 ,使语法看起来像对我来说很奇怪,这些变量 strnext 没有声明为指针的情况,不是必需的吗?

最后,还有while循环,我猜它会一直执行到找到[=22=末尾的[=21=]元素] 细绳。但是,再次使用 pathNode = malloc(sizeof(Node));pathNode->str = token;pathNode->next = head;,让我回到之前的困惑...

你的问题好像是关于单链表的。该函数将节点插入到单链表中。

分配pathNode,分配为head

strtok 将字符串分成标记,第一个标记用于 head.

如果下一个令牌成功,它会分配另一个节点,该节点成为新的headpathNode->next = head表示下一个元素为head。然后它分配 head = pathNode,并继续循环。

"pathNode is a NULL value, I mean, how could that be possible if the "Node" type variable is fixed (at least initially)"

pathNode如果内存不足可以NULLmalloc失败

"However, there's again the use of pathNode = malloc(sizeof(Node));"

head 的开头有一个 malloc,在以下节点的循环内部有 malloc

此外,还有一些问题。该函数使用 pathCopy 来复制源字符串。这是正确的方法,因为 strtok 将修改其源代码。但是 pathCopy 应该在最后被释放。 return 对来电者来说用处不大。

总的来说,这个函数比它需要的更复杂。这是一个更简单的例子:

Node* create_node(const char* str)
{
    Node* node = malloc(sizeof(Node)); if (!node) return NULL;
    node->str = strdup(str);
    node->next = NULL;
    return node;
}

Node* mygetdir(const char* source)
{
    if (!source) return NULL;
    char *path = strdup(source);
    if (!path) return NULL;

    Node* head = NULL;
    char* token = strtok(path, ":");
    while (token)
    {
        Node* save = head;
        head = create_node(token); if (!head) return NULL;
        head->next = save;
        token = strtok(NULL, ":");
    }

    free(path);
    return head;
}

您可以打印如下。你必须在最后释放链表。

int main(void)
{
    Node* head = mygetdir("/sbin1:/usr/sbin2:/bin3:/usr/bin4:/usr/local/bin5");
    Node* node = head;
    while (node)
    {
        printf("ID = %s\n", node->str);
        node = node->next;
    }

    node = head;
    while (node)
    {
        Node* next = node->next;

        // ******* EDIT
        // don't call `free(node->str)` if using your own version
        // because in your own version node->str is just a pointer to `pathCopy`
        free(node->str);

        free(node);
        node = next;
    }

    return 0;
}