这个为任何环境字符串创建链接列表的函数应该如何工作?
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;
,它们类似于某种 变量声明反转 ,使语法看起来像对我来说很奇怪,这些变量 str
和 next
没有声明为指针的情况,不是必需的吗?
和最后,还有while循环,我猜它会一直执行到找到[=22=末尾的[=21=]
元素] 细绳。但是,再次使用 pathNode = malloc(sizeof(Node));
、 pathNode->str = token;
和 pathNode->next = head;
,让我回到之前的困惑...
你的问题好像是关于单链表的。该函数将节点插入到单链表中。
分配pathNode
,分配为head
。
strtok
将字符串分成标记,第一个标记用于 head
.
如果下一个令牌成功,它会分配另一个节点,该节点成为新的head
。 pathNode->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
如果内存不足可以NULL
malloc
失败
"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;
}
代码如下:
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;
,它们类似于某种 变量声明反转 ,使语法看起来像对我来说很奇怪,这些变量 str
和 next
没有声明为指针的情况,不是必需的吗?
和最后,还有while循环,我猜它会一直执行到找到[=22=末尾的[=21=]
元素] 细绳。但是,再次使用 pathNode = malloc(sizeof(Node));
、 pathNode->str = token;
和 pathNode->next = head;
,让我回到之前的困惑...
你的问题好像是关于单链表的。该函数将节点插入到单链表中。
分配pathNode
,分配为head
。
strtok
将字符串分成标记,第一个标记用于 head
.
如果下一个令牌成功,它会分配另一个节点,该节点成为新的head
。 pathNode->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
如果内存不足可以NULL
malloc
失败
"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;
}