假设我有以下结构:
struct _node {
int id;
char *name;
struct node *next;
};
我想编写一个遍历链表的函数,并查找名称成员包含某个子字符串的结构,并将这些结构添加到新的链表中并返回新的链表。
我尝试使用strstr这样做,但在某些时候我得到一个无限循环,我无法弄清楚无限循环发生的确切原因。
这是我的功能:
struct _node *containSubstr(struct _node *head, char needle[]) {
if (head == NULL) {
printf("BLOOP BLEEP BOOP BEEP.\n");
exit(EXIT_FAILURE);
}
struct _node *curr = head;
struct _node *returnHead = createEmptyNode();
while (curr != NULL) {
char haystack[strlen(curr->name)];
strcpy(haystack, curr->name);
strToLower(needle);
strToLower(haystack);
if (strstr(haystack, needle) != NULL) {
// this is where I get the infinite loop
append(returnHead, curr);
}
curr = curr->next;
}
return returnHead;
}
函数append和createEmptyNode经过测试并正常工作。
我多次查看逻辑,我认为这必须有效。我用print语句填充了我的代码,似乎在找到包含子字符串的所有节点后,它不断重复最后一个节点并进入无限循环。
这是我的追加功能:
void append(struct _node *head, struct _node *newNode) {
if (head == NULL) {
printf("BLOOP BLEEP BOOP BEEP.\n");
exit(EXIT_FAILURE);
}
struct _node *curr = head;
if(curr == NULL) {
head = newNode;
}
else {
while(curr->next != NULL) {
curr = curr->next;
}
curr->next = newNode;
}
}
答案 0 :(得分:1)
想象一下这种情况:你有一个列表 L ,它只包含链表中的2个节点( A 和 B )。想象一下,节点 A 和 B 都包含您要查找的子字符串:
原始列表 L :
A-> B-> NULL
因此,在第一次迭代后,您的新列表 L2 应如下所示:
A-> NULL
但是在您的追加功能中,您不会创建新节点的深层副本。因此,您的新列表 L2 如下所示:
Empty_node-> A-> B-> NULL
在下一步中,您将移至节点 B 。所以你拿 L2 并在那里附加 B 。第二次迭代后,您的 L2 如下所示:
Empty_node-> A-> B-> B(B指向自身)。
由于您没有创建深层副本,因此您实际上始终使用列表 L ,并且当您将节点 B 附加到您认为的列表 L2时您实际上将 B 附加到 L ,然后 B 指向自己curr->next = newNode;
append
功能)。因此,在下一次迭代中,您再次询问 B 是否包含您要查找的字符串。
<强>结论强>
创建新列表时需要创建深层副本。
在当前设置中,append
功能会修改原始列表。