c - 为什么我的所选元素的清除功能无法正常工作?

标签 c pointers linked-list

在学校的项目中,我发现了一个小问题,我不知道如何解决。 问题出在clear_train 上。当我尝试删除 1. 元素时,函数也返回我的元素(但为空)。 这是我的源代码,其中是所有函数的定义: (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;
}

最后有输出:

            //there is empty node
Bratislava
Levoca
Spiska Nova Ves
Bardejov
Pichne

最佳答案

从链表中删除节点变得比实际需要的更加困难。虽然每次调用 clear_train 时您都可以自由地返回并分配头节点,但这并不是真正的方法。

不要将指向头的指针(first)作为参数传递给clear_train,而是传递头指针的实际地址,例如

clear_train(&train,"Presov");

这样你就可以直接操作该地址处的值(节点)。如果列表中的第一个节点是要删除的节点,则只需将原始指针保存的节点地址更新为新的第一个节点即可。

无需尝试保留上一个、当前和下一个节点,只需使用指向当前节点的指针即可。然后,当找到包含 target 的节点时,只需将该地址处的指针更新为 ->next 节点即可。请参阅Linus on Understand Pointers

这会将您的 clear_train 函数简化为:

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;
        }
    }
}

比尝试测试节点所在位置的不同情况简单得多。

关于c - 为什么我的所选元素的清除功能无法正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58780881/

相关文章:

c++ - 通过引用或指针传递 vector

java - 重复链表值

c - 0 - (-128) 与 2 的补码等于多少?

c - fork() 的子进程过多

delphi - 帕斯卡指针改变其指向值

c++ - 独立于平台的 C++ 调试器 IDE,遵循 Visual Studio 等指针

java - 为什么下面的语句在 C 中合法而在 Java 中不合法?

c - C 中的英特尔 AVX 乘法错误,

我的链接列表的清晰度

c - 使用指针对数组进行链表遍历