链表C的分段错误

链表C的分段错误,c,data-structures,linked-list,C,Data Structures,Linked List,我正在为一个类创建一个链表,但在搜索和打印时,我总是遇到分段错误。我认为这与数据结构没有正确地进行malloced有关,但我尝试了很多方法,但我得到了相同的错误。任何帮助都会很好 struct LList_data { int x; int y; } struct LList { struct LList_data * data; // data=(struct LList_data *)malloc(si

我正在为一个类创建一个链表,但在搜索和打印时,我总是遇到分段错误。我认为这与数据结构没有正确地进行malloced有关,但我尝试了很多方法,但我得到了相同的错误。任何帮助都会很好

    struct LList_data {
        int x;
        int y;
    }

    struct LList {
        struct LList_data * data;
        // data=(struct LList_data *)malloc(sizeof(struct LList_data));
        struct LList * next;
    }

struct LList * LList_create()
{
        struct LList * list;
        list = (struct LList *)malloc(sizeof(struct LList));
        list->next = NULL;
        return list;
}
    void LList_push_front(struct LList * list, struct LList_data newdata)
    {
        struct LList * node;
        struct LList_data * data;
        node = (struct LList *)malloc(sizeof(struct LList));
        data = (struct LList_data *)malloc(sizeof(struct LList_data));

        node->data = data;

        node->data->x = newdata.x;
        node->data->y = newdata.y;

        node->next=list->next;
        list->next=node;
        return;
    }

    int LList_find(struct LList * list, int x, struct LList_data * data)
    {
            struct LList * node;

    //      if(list == NULL)
    //      printf("list empty");
    //      if(!list->next==NULL)
    //      printf("list next empty");

            for(node=list->next; node!= NULL; node=node->next){
              if(x == node->data->x){
                node->data=data;
                return 1;
                }
            }

            return 0;
    }

    int LList_update(struct LList * list, struct LList_data newData)
    {
            struct LList * node;

            node = list->next;
            while(node)
            {
              if(node->data->x == newData.x)
              {
              node->data = &newData;
              return 1;
              }
              node=node->next;
            }
            return 0;
    }

    int LList_remove(struct LList * list, int x, struct LList_data * data)
    {
            struct LList * node;
            struct LList * prev;
            node = list->next;

            while(node)
            {
              prev = node;
              node = node->next;
            }
            if(node == NULL)
              return 0;

            prev->next = node->next;
            return 1;
    }

    void LList_destroy(struct LList * list)
    {
            struct LList * temp = list->next;
            struct LList * next;

            while(temp)
            {
              next = temp->next;
              free(temp);
              temp = next;
            }
            free(list);
    }

    void LList_print(struct LList * list)
    {
            struct LList * temp;
            temp=list;
            if(temp!=NULL){
            while(temp!=NULL)
              {
              printf("%d,%d",temp->data->x, temp->data->y);
              temp=temp->next;
              }
            temp->next = (struct LList *)malloc(sizeof(struct LList));
            temp->next = NULL;
            }
    }
下面是列表的用途

#include"llist.h"
#include<stdio.h>
#include<stdlib.h>

void menu();
void a(struct LList * list);
void c(struct LList * list);
void f(struct LList * list);
void r(struct LList * list);
void p(struct LList * list);

int main(){
        menu();
        return 0;
}


void menu()
{
        char choice;
        struct LList * list;

        list = LList_create();

        scanf(" %c", &choice);

        switch(choice){
          case 'a':
          case 'A':
                a(list);
                break;
          case 'C':
          case 'c':
                c(list);
                return;
                break;
          case 'f':
          case 'F':
                f(list);
                return;
                break;
          case 'r':
          case 'R':
                r(list);
                return;
                break;
          case 'p':
          case 'P':
                p(list);
                return;
                break;
          default:
                fprintf(stderr, "Invalid choice \n");
                menu();
                return;
        }
}

void a(struct LList * list)
{
        int x;
        struct LList_data data;

        scanf(" %d", &x);
        data.x = x;
        data.y = 0;

        LList_push_front(list,data);

        printf("%d,%d \n", data.x,data.y);

        menu();
        return;
}
void c(struct LList * list)
{
        LList_destroy(list);
        list =  LList_create();

        menu();
        return;

}

void f(struct LList * list)
{
        int x;

        struct LList_data * data;
        data=NULL;

        scanf(" %d", &x);

        LList_find(list, x, data);

        data->y += 1;

        printf("%d,%d", data->x,data->y);

        menu();
        return;
}

void r(struct LList * list)
{
        int x;
        struct LList_data * data;
        scanf(" %d", &x);

        data=NULL;

        LList_find(list, x, data);

        printf("%d,%d", data->x,data->y);

        LList_remove(list, x, data);

        menu();
       return;
}
void p(struct LList * list)
{
        LList_print(list);

        menu();
        return;
}
#包括“llist.h”
#包括
#包括
无效菜单();
作废a(结构列表*列表);
void c(结构列表*list);
void f(结构列表*列表);
void r(结构列表*list);
void p(结构列表*list);
int main(){
菜单();
返回0;
}
无效菜单()
{
字符选择;
struct-LList*列表;
list=LList_create();
scanf(“%c”,选择(&c));
开关(选择){
案例“a”:
案例“A”:
a(名单);
打破
案例“C”:
案例“c”:
c(名单);
返回;
打破
案例“f”:
案例“F”:
f(名单);
返回;
打破
案例“r”:
案例“R”:
r(名单);
返回;
打破
案例“p”:
案例“P”:
p(名单);
返回;
打破
违约:
fprintf(stderr,“无效选择”);
菜单();
返回;
}
}
作废a(结构列表*列表)
{
int x;
struct-LList_数据;
scanf(“%d”和&x);
数据x=x;
数据y=0;
list_push_front(列表、数据);
printf(“%d,%d\n”,data.x,data.y);
菜单();
返回;
}
void c(结构列表*list)
{
销毁(清单);
list=LList_create();
菜单();
返回;
}
void f(结构列表*list)
{
int x;
struct LList_data*数据;
数据=空;
scanf(“%d”和&x);
list_find(列表、x、数据);
数据->y+=1;
printf(“%d,%d”,数据->x,数据->y);
菜单();
返回;
}
void r(结构列表*list)
{
int x;
struct LList_data*数据;
scanf(“%d”和&x);
数据=空;
list_find(列表、x、数据);
printf(“%d,%d”,数据->x,数据->y);
删除(列表、x、数据);
菜单();
返回;
}
void p(结构列表*list)
{
列印(列表);
菜单();
返回;
}
有几件事

从子函数(例如
p
)递归调用
菜单
)不是一件好事。在
main

打印功能正在添加新元素

find函数只返回0/1,但从未返回指向“found”元素的指针

我已经注释并修复了[大部分]bug。当我这样做时(如果可能),我将您的原始代码保留在
#if 0
中,并将更正后的代码保留在相应的
#else
部分。注释更详细地说明了一些问题是什么。我希望比较原始代码和修改后的代码会有所启发

我必须更改一些链表函数参数/返回值,以便它们有意义

不管怎么说,下面是代码,为了简单起见,我将其合并到一个文件中[请原谅这种不必要的风格清理]:

//#include "llist.h"
#include <stdio.h>
#include <stdlib.h>

struct LList_data {
    int x;
    int y;
};

struct LList {
    struct LList_data *data;
    // data=(struct LList_data *)malloc(sizeof(struct LList_data));
    struct LList *next;
};

struct LList *
LList_create()
{
    struct LList *list;

    list = (struct LList *) malloc(sizeof(struct LList));
    list->next = NULL;

    return list;
}

void
LList_push_front(struct LList *list, struct LList_data newdata)
{
    struct LList *node;
    struct LList_data *data;

#if 0
    node = (struct LList *) malloc(sizeof(struct LList));
    data = (struct LList_data *) malloc(sizeof(struct LList_data));
#else
    node = malloc(sizeof(*node));
    data = malloc(sizeof(*data));
#endif

    node->data = data;

    node->data->x = newdata.x;
    node->data->y = newdata.y;

    node->next = list->next;
    list->next = node;

    return;
}

#if 0
int
LList_find(struct LList *list, int x, struct LList_data *data)
{
    struct LList *node;

    // if(list == NULL)
    // printf("list empty");
    // if(!list->next==NULL)
    // printf("list next empty");

    // NOTE/BUG: this entire function is just to _find_ a node [to be used by
    // other functions], so it should _not_ try to change anything

    for (node = list->next; node != NULL; node = node->next) {
        // NOTE/BUG: this replaces node->data without freeing it first (i.e.
        // this is a memory leak)
        if (x == node->data->x) {
            node->data = data;
            return 1;
        }
    }

    return 0;
}

#else
struct LList_data *
LList_find(struct LList *list, int x)
{
    struct LList *node;
    struct LList_data *data;

    data = NULL;
    for (node = list->next; node != NULL; node = node->next) {
        if (x == node->data->x) {
            data = node->data;
            break;
        }
    }

    return data;
}
#endif

int
LList_update(struct LList *list, struct LList_data newData)
{
    struct LList *node;

    node = list->next;
    while (node) {
        // NOTE/BUG: newData is on the _stack_ and when this function returns
        // newData will go out of scope (i.e. node->data will become invalid)
#if 0
        if (node->data->x == newData.x) {
            node->data = &newData;
            return 1;
        }
#else
        // NOTE/FIX: reuse the existing data cell and populate with new data
        if (node->data->x == newData.x) {
            *node->data = newData;
            return 1;
        }
#endif
        node = node->next;
    }
    return 0;
}

int
LList_remove(struct LList *list, /*-int x,-*/ struct LList_data *data)
{
    struct LList *node;
    struct LList *next;
    struct LList *prev;

    prev = NULL;

    // NOTE: passing "x" really not required since "data" points to the node
    // to be removed

    for (node = list->next;  node != NULL;  node = next) {
        next = node->next;
        if (node->data == data)
            break;
        prev = node;
    }

    if (node != NULL) {
        if (prev != NULL)
            prev->next = next;
        else
            list->next = next;
        free(node->data);
        free(node);
    }
}

void
LList_destroy(struct LList *list)
{
    struct LList *temp = list->next;
    struct LList *next;

#if 0
    // NOTE/BUG: this does _not_ free the data associated with each list
    // element (i.e. a memory leak)
    while (temp) {
        next = temp->next;
        free(temp);
        temp = next;
    }
#else
    while (temp) {
        next = temp->next;

        free(temp->data);
        free(temp);

        temp = next;
    }
#endif

    free(list);
}

void
LList_print(struct LList *list)
{
    struct LList *temp;

    // NOTE/BUG: a list print function has no need to add to or change the
    // list
#if 0
    temp = list;
    if (temp != NULL) {
        while (temp != NULL) {
            printf("%d,%d", temp->data->x, temp->data->y);
            temp = temp->next;
        }
        temp->next = (struct LList *) malloc(sizeof(struct LList));
        temp->next = NULL;
    }
#else
    for (temp = list->next;  temp != NULL;  temp = temp->next)
        printf("%d,%d\n", temp->data->x, temp->data->y);
#endif
}

void menu(void);
void a(struct LList *list);
struct LList *c(struct LList *list);
void f(struct LList *list);
void r(struct LList *list);
void p(struct LList *list);

struct LList *mainlist;

int
main()
{

    mainlist = LList_create();

    while (1) {
        menu();
    }

    return 0;
}

void
menu(void)
{
    struct LList *list;
    char choice;

    list = mainlist;

    printf("a -- a new element\n");
    printf("c -- recreate empty list\n");
    printf("f -- find list element and increment\n");
    printf("r -- remove element from list\n");
    printf("p -- print list\n");
    printf("menu> ");
    fflush(stdout);

    scanf(" %c", &choice);

    switch (choice) {
    case 'a':
    case 'A':
        a(list);
        break;

    case 'C':
    case 'c':
        mainlist = c(list);
        //return;
        break;

    case 'f':
    case 'F':
        f(list);
        //return;
        break;

    case 'r':
    case 'R':
        r(list);
        //return;
        break;

    case 'p':
    case 'P':
        p(list);
        //return;
        break;

    default:
        fprintf(stderr, "Invalid choice \n");
#if 0
        menu();
        return;
#endif
        break;
    }
}

void
a(struct LList *list)
{
    int x;
    struct LList_data data;

    printf(" Enter value to add: ");
    fflush(stdout);
    scanf(" %d", &x);

    data.x = x;
    data.y = 0;

    LList_push_front(list, data);

    printf("%d,%d \n", data.x, data.y);

#if 0
    menu();
    return;
#endif
}

struct LList *
c(struct LList *list)
{

    LList_destroy(list);

    // NOTE/BUG: "list" goes out of scope, so recreating it here has no useful
    // effect without returning the value
    list = LList_create();

#if 0
    menu();
    return;
#endif

    return list;
}

void
f(struct LList *list)
{
    int x;

    struct LList_data *data;

    data = NULL;

    printf(" Enter value to find/increment: ");
    fflush(stdout);
    scanf(" %d", &x);

    data = LList_find(list, x);
    if (data != NULL) {
        data->y += 1;
        printf("%d,%d\n", data->x, data->y);
    }

#if 0
    menu();
    return;
#endif
}

void
r(struct LList *list)
{
    int x;
    struct LList_data *data;

    printf(" Enter value to remove: ");
    fflush(stdout);
    scanf(" %d", &x);

    data = NULL;

    // NOTE/BUG: "data" will always be null because LList_find never set it
    // to anything
#if 0
    LList_find(list, x, data);
    printf("%d,%d\n", data->x, data->y);
#else
    data = LList_find(list, x);
    if (data != NULL) {
        printf("%d,%d\n", data->x, data->y);
        LList_remove(list, data);
    }
#endif

#if 0
    menu();
    return;
#endif
}

void
p(struct LList *list)
{
    LList_print(list);

#if 0
    menu();
    return;
#endif
}
/#包括“llist.h”
#包括
#包括
结构LList_数据{
int x;
int-y;
};
结构主义者{
struct LList_data*数据;
//data=(struct-LList_-data*)malloc(sizeof(struct-LList_-data));
struct-LList*next;
};
结构主义者*
list_create()
{
struct-LList*列表;
list=(struct-LList*)malloc(sizeof(struct-LList));
列表->下一步=空;
退货清单;
}
无效的
LList\u推送\u前端(结构LList*列表,结构LList\u数据newdata)
{
struct-LList*节点;
struct LList_data*数据;
#如果0
node=(struct-LList*)malloc(sizeof(struct-LList));
data=(struct-LList_-data*)malloc(sizeof(struct-LList_-data));
#否则
node=malloc(sizeof(*node));
数据=malloc(sizeof(*数据));
#恩迪夫
节点->数据=数据;
节点->数据->x=newdata.x;
节点->数据->y=newdata.y;
节点->下一步=列表->下一步;
列表->下一步=节点;
返回;
}
#如果0
int
list_find(struct-list*list,int x,struct-list_data*data)
{
struct-LList*节点;
//if(list==NULL)
//printf(“列表为空”);
//如果(!list->next==NULL)
//printf(“下一个空列表”);
//注意/错误:整个函数只是为了找到一个节点[供用户使用]
//所以它不应该试图改变任何东西
对于(节点=列表->下一步;节点!=NULL;节点=节点->下一步){
//注意/错误:这将替换节点->数据,而不首先释放它(即。
//这是内存泄漏)
如果(x==节点->数据->x){
节点->数据=数据;
返回1;
}
}
返回0;
}
#否则
结构LList_数据*
LList_find(结构LList*列表,整数x)
{
struct-LList*节点;
struct LList_data*数据;
数据=空;
对于(节点=列表->下一步;节点!=NULL;节点=节点->下一步){
如果(x==节点->数据->x){
数据=节点->数据;
打破
}
}
返回数据;
}
#恩迪夫
int
LList_更新(struct-LList*列表,struct-LList_数据newData)
{
struct-LList*节点;
节点=列表->下一步;
while(节点){
//注意/错误:newData位于_stack_uu上,当此函数返回时
//新数据将超出范围(即节点->数据将变为无效)
#如果0
如果(节点->数据->x==newData.x){
节点->数据=&newData;
返回1;
}
#否则
//注意/修复:重用现有数据单元并填充新数据
如果(节点->数据->x==newData.x){
*节点->数据=新数据;
返回1;
}
#恩迪夫
节点=节点->下一步;
}
返回0;
}
int
LList_remove(struct-LList*list、/*-int x、*/struct-LList_data*data)
{
struct-LList*节点;
struct-LList*next;
struct-LList*prev;