[英]Why my clear function with selected element does not work correctly?
在上学的项目工作期间,我发现了一个小问题,我不知道要删除。 问题在于功能 clear_train。 当我尝试删除 1. 元素时,function 也返回我的元素(但为空)。 这是我的源代码,其中所有函数的定义:(在 a_train.h 中是函数的声明和描述)
#include "a_train.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct car* add_car(struct car* first,const char* target) {
struct car* adder = malloc(sizeof(struct car));
struct car *current = first;
strcpy (adder->value,target);
adder->next=NULL;
if(first == NULL){
first =adder;}
else{
while (current->next != NULL) {
current = current->next;
}
current->next = adder;
}
return first ;
}
void print_train(struct car* first) {
if (first!=NULL){
while (first!=NULL){
printf("%s\n",first->value);
first=first->next;
}
}
else printf("empty list\n");
}
void cancel_train(struct car* first) {
while(first!=NULL){
struct car* canceler = first->next;
free(first);
first=canceler;
}
}
struct car* clear_train(struct car* first, const char* target) {
if(first == NULL){
return NULL;
}else if (first->next==NULL){
if(strcmp(first->value,target)==0){
free(first);
return NULL;
}else return first;
}
struct car* prev_searcher =first;
struct car* this_searcher =first;
while (this_searcher!=NULL){
if(strcmp(this_searcher->value,target)==0){
prev_searcher->next=this_searcher->next;
free(this_searcher);
}
prev_searcher=this_searcher;
this_searcher=this_searcher->next;
}
return first;
}
这里是链表的定义:
struct car {
char value[SIZE];
struct car* next;
};
我调用函数的主要源代码:
int main(){
struct car* train = NULL;
train = add_car(train,"Presov");
train = add_car(train,"Bratislava");
train = add_car(train,"Levoca");
train = add_car(train,"Spiska Nova Ves");
train = add_car(train,"Bardejov");
train = add_car(train,"Pichne");
clear_train(train,"Presov");
print_train(train);
cancel_train(train);
return 0;
}
最后是 output:
//there is empty node
Bratislava
Levoca
Spiska Nova Ves
Bardejov
Pichne
在clear_train
当您找到汽车时-您释放该元素,然后尝试再次找到它,因此该程序会给您带来麻烦。 像这样写
if(strcmp(this_searcher->value,target)==0){
prev_searcher->next=this_searcher->next;
free(this_searcher);
return prev_searcher}
您使从链表中删除节点变得比需要的更困难。 虽然每次调用clear_train
时您都可以自由地返回并分配头节点,但这并不是真正的方法。
不是将指向头的指针( first
)作为参数传递给clear_train
,而是传递头指针的实际地址,例如
clear_train(&train,"Presov");
这样您就可以直接操作该地址处的值(节点)。 如果列表中的第一个节点是要删除的节点,则只需将原始指针持有的节点地址更新为新的第一个节点即可。
无需尝试保留前一个、当前和下一个节点,只需使用指向当前节点的指针即可。 然后,当找到包含target
的节点时,只需将该地址处的指针更新为->next
节点即可。 请参阅了解指针的 Linus
这会将您的clear_train
function 减少到:
void clear_train (struct car **first, const char* target) {
struct car **ppn = first; /* pointer-to-pointer to first */
struct car *pn = *first; /* pointer-to-first */
for (; pn; ppn = &pn->next, pn = pn->next) { /* iterate, find target */
if (strcmp (pn->value, target) == 0) { /* if found */
*ppn = pn->next; /* set pointer at target address = next */
free (pn); /* free node contianing target */
break;
}
}
}
比尝试测试节点所在位置的不同情况要简单得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.