繁体   English   中英

为什么我的带有选定元素的清除 function 不能正常工作?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM