【问题标题】:Problems with removing the last item in a linked list in c在c中删除链表中最后一项的问题
【发布时间】:2016-09-10 12:09:59
【问题描述】:

我刚学c,关于链表我有一些大问题。

我有以下代码:

#include <stdio.h>
#include <stdlib.h>
struct people {
    int age;
    char *name;
    struct people * next;
};
typedef struct people people;

void count(people array) {
    people *current=malloc(sizeof(people));
    current = &array;
    int count = 0;
    while(current){
        count++;
        printf("name %s\n",current->name);
        printf("age %d\n",current->age);
        current=current->next;
    }
    printf("%d\n", count);
    free(current);
}
void push(people *array){
    people * new=malloc(sizeof(people));
    people *last=malloc(sizeof(people));
    new->age=300;
    new->name="baz";
    new->next=NULL;
    last=array;
    while(last->next){
        last=last->next;
    }
    last->next=new;
//    free(new);
}
void pop(people *array){
    people * last=malloc(sizeof(people));
    last=array;
    while(last->next){
        //get the last element in the list
        last=last->next;
    }
//    free the last element 
    free(last);
}
int main(int argc, char** argv) {
    people person = {
        .name = "foo",
        .age = 25
    };
    person.next = malloc(sizeof (people));
    person.next->age = 26;
    person.next->name = "bar";
    person.next->next = NULL;
    //push into the list
    push(&person);
    //count after pushing
    count(person);
    //remove last
    pop(&person);
    //at this count i get just the age 0 but the name was not removed and still counts 3
    count(person);
    return 0;
}

当我运行 pop 时,它的工作方式应该类似于 Javascript 中的 Array.prototype.pop
最后一个next 的行为非常奇怪,其名称为“baz”,年龄为 300。在我运行此代码而不是删除最后一个结构后,它只显示年龄为 0。

似乎 free 并没有真正释放使用 malloc 分配的指针。

【问题讨论】:

  • 虽然最后一个仍然指向无效内存。 free() 只是将给定的内存块返回给内存分配器,不会将指针设置为有效内存
  • 除了@GeorgeAl 评论之外,您还泄漏了大量内存。当前和最后一次获得自己的内存,然后您只需通过将指针分配给其他地址来删除它。
  • @nikoss,你需要设置one-before-last-&gt;next = NULL;。也可以尝试向自己解释为什么要尽可能地使用malloc()。例如,为什么pop()malloc() 在第一行?
  • @nikoss,你需要一本好的 C 入门书
  • @nikoss 好的。我建议你不要通过编码和调试从头开始学习 c。指针和内存并没有那么复杂,但你可以对它的工作原理进行逆向工程。

标签: c arrays struct linked-list malloc


【解决方案1】:

例子

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct people {
    int age;
    char *name;
    struct people * next;
} people;


people *new_people(const char *name, int age){
    people *node = malloc(sizeof(people));
    char *copy_name = malloc(strlen(name)+1);
    strcpy(copy_name, name);

    node->age = age;
    node->name = copy_name;
    node->next = NULL;
    return node;
}

void free_people(people *p){
    free(p->name);
    free(p);
}

void count(people *array) {
    people *current = array;
    int count = 0;

    while(current){
        count++;
        printf("name %s\n", current->name);
        printf("age %d\n",  current->age);
        current = current->next;
    }
    printf("%d\n", count);
}

void push(people **array, people *addNode){
    if(*array == NULL){
        *array = addNode;
        return ;
    }

    people *last = *array;
    while(last->next){
        last = last->next;
    }
    last->next = addNode;
    //return length;
}

people *pop(people **array){
    if(*array == NULL)
        return NULL;

    people *last = *array;
    people *prev = NULL;
    while(last->next){
        prev = last;
        last=last->next;
    }
    if(prev != NULL)
        prev->next = NULL;
    else
        *array = NULL;
    return last;
}

int main(void) {
    people *array = NULL;
    push(&array, new_people("foo",  25));
    push(&array, new_people("bar",  26));
    push(&array, new_people("baz", 300));

    count(array);
    people *baz = pop(&array);
    free_people(baz);
    count(array);

    people *bar = pop(&array);
    free_people(bar);
    people *foo = pop(&array);
    free_people(foo);//free_people(pop(&array))

    return 0;
}

【讨论】:

    【解决方案2】:

    问题在于,在void count(people array) 中,current=current-&gt;next; 将在 while 循环中分配。所以你需要确保last->next在pop函数中被赋值为NULL。

    我将你的 pop 函数修改为:

    void pop(people *array){
    
        people * last=malloc(sizeof(people));
    
        while(array->next){
            last=array;
            array=array->next;
            if(array->next){
                 //get the last element in the list
                 last=last->next;
            }else{
                 break;
            }                                                                                            
        }
        last->next=NULL;
        array=last;
    }
    

    在pop函数中,你应该将'array'的地址分配给'last',然后将'array'指向'array->next'。

    当程序从 while 循环中中断时,您可以执行 last-&gt;next=NULL;array=last; 以确保最后一个结构正常。

    【讨论】:

      猜你喜欢
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 2017-12-31
      相关资源
      最近更新 更多