C 从链接列表中删除节点时遇到问题
我一直在为我正在创建的shell编写这段代码,但由于某些原因,它不起作用。我正在实现一个watchuser函数,当给定一个参数时,watch就是一个用户(args[1])。但是,当给出“off”的第二个参数(args[2])时,应将该用户从链表中删除,并且不再监视该用户C 从链接列表中删除节点时遇到问题,c,linked-list,C,Linked List,我一直在为我正在创建的shell编写这段代码,但由于某些原因,它不起作用。我正在实现一个watchuser函数,当给定一个参数时,watch就是一个用户(args[1])。但是,当给出“off”的第二个参数(args[2])时,应将该用户从链表中删除,并且不再监视该用户 struct userList * goList; goList = userInventory; do{ if (strcmp(userInventory->username, args[1]) == 0){
struct userList * goList;
goList = userInventory;
do{
if (strcmp(userInventory->username, args[1]) == 0){
printf("%s\n", args[1]);
printf("%s\n",userInventory->username);
struct userList * temp2;
temp2 = userInventory->next;
if (userInventory->next != NULL){
userInventory->next = temp2->next;
userInventory->next->prev = userInventory;
}
free(temp2);
}
goList = goList->next;
}while (goList != userInventory);
我的全局结构也如下所示:
struct userList{
char * username;
struct userList * prev;
struct userList * next;
}
因此,此代码不会从我的链接列表中删除用户节点。添加工作,但这个删除功能不会,我不知道为什么。print语句只是为了确保它正在执行它所执行的条件
如果有人能帮我找到错误背后的原因,我将不胜感激。在那之前,我会试着调试这个
谢谢 如果我了解你的代码 问题1(似乎合理): 这是循环列表吗?如果不是,则
while()
中的条件将不会变为真
问题2:
goList = userInventory;
do {
if (strcmp(userInventory->username, args[1]) == 0) {
...
}
goList = goList->next;
} while (goList != userInventory);
在这里,您将继续比较列表头部(或尾部)的字符串,而不是比较当前节点中的字符串,goList
。如果匹配位于userInventory
最初指向的第一个节点(head/tail),则只能在上述代码中成功查找匹配
问题3:
temp2 = userInventory->next;
if (userInventory->next != NULL) {
userInventory->next = temp2->next;
userInventory->next->prev = userInventory;
}
free(temp2);
让我们假设userInventory
已更正为goList
:
temp2 = goList->next;
if (goList->next != NULL) {
goList->next = temp2->next;
goList->next->prev = goList;
}
free(temp2);
首先,它将free()
不是匹配的节点,而是它后面的节点(甚至可能NULL
),这是错误的
其次,这段代码没有对节点进行适当的取消链接和重新链接。应该是什么(假设列表不是循环的):
问题4:
do {
if (strcmp(goList->username, args[1]) == 0) {
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
free(temp2);
}
goList = goList->next;
} while (...);
如果删除成功,此行将访问刚刚释放的节点并可能使程序崩溃:
goList = goList->next;
因此,您需要将代码更改为:
do {
if (strcmp(goList->username, args[1]) == 0) {
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
goList = goList->next;
free(temp2);
}
else
{
goList = goList->next;
}
} while (...);
问题5:
goList = userInventory;
如果删除列表头(或是尾部?)节点,则需要更新userInventory
以指向它后面的下一个节点。否则,您将失去对列表的所有访问权限,因为userInventory
将指向已释放的内存,而不是剩余的节点(如果有)
问题6(似乎合理):
上面的行没有free()
内存temp2->username
。如果它是malloc()
ed,您希望free()
it
您应该一步一个脚印地解决问题(例如,首先迭代列表,然后取消链接/重新链接节点,然后删除节点)
当事情不清楚或不起作用时,用纸和铅笔(或画板、钢笔或粉笔)自己想象问题。绘制对象、描绘指针的箭头或它们之间的其他连接等,在对象旁边涂鸦变量名称,以便清楚地看到如何从图表到代码的过程。您能给出一个最简单的完整示例吗?您的意思是什么?比如你到底在寻找什么?我指的是我们可以复制、粘贴、编译和运行的代码,它将演示错误,并且尽可能短和简单,并且仍然满足这些要求。我建议你使用调试器逐行检查代码,检查所有变量、成员、字符串和指针。那么问题就很明显了。这个列表应该是一个戒指吗?我仔细阅读了代码,确实找到了您在这里讨论的大多数问题。我的代码现在可以工作了,我已经筋疲力尽了。谢谢你的帮助。我非常感激,我会接受你的建议,在我实际构建它之前,先画一个链表。不管怎样,它仍然不起作用。它不是一个循环链表,它是一个双链表。我尝试将do-while循环变成while循环,其中条件为(goList!=NULL),但这不起作用。你会建议把高尔夫球手全部除掉,改用userInventory(我的主列表)吗?如果你继续推进
userInventory
,你需要恢复它。为什么要麻烦?只需使用高尔夫球手。把问题分成几个小问题。画一个子问题。编码。调试它。继续下一个。
do {
if (strcmp(goList->username, args[1]) == 0) {
temp2 = goList;
if (goList->next != NULL) {
goList->next->prev = goList->prev; // now goList->next node points to goList->prev node
}
if (goList->prev != NULL) {
goList->prev->next = goList->next; // now goList->prev node points to goList->next node
}
goList = goList->next;
free(temp2);
}
else
{
goList = goList->next;
}
} while (...);
goList = userInventory;
free(temp2);