C 使用结构和动态内存分配的队列

C 使用结构和动态内存分配的队列,c,pointers,struct,linked-list,C,Pointers,Struct,Linked List,我的任务是用C语言制作一个队列数据结构,作为一个链表。我们的讲师给了我们大量代码来实现堆栈,但我们必须对其进行调整以创建队列。我们的讲师给我们的代码最终没有在与我为队列编写的代码完全相同的点编译和分段错误。我对structs、malloc和C一般来说都是新手,所以我可能忽略了一些非常明显的东西 以下是我正在使用的代码: #include <stdio.h> #include <stdlib.h> struct node{ int data;

我的任务是用C语言制作一个队列数据结构,作为一个链表。我们的讲师给了我们大量代码来实现堆栈,但我们必须对其进行调整以创建队列。我们的讲师给我们的代码最终没有在与我为队列编写的代码完全相同的点编译和分段错误。我对structs、malloc和C一般来说都是新手,所以我可能忽略了一些非常明显的东西

以下是我正在使用的代码:

#include <stdio.h>
#include <stdlib.h>
struct node{
    int data;               //contains the actual data
    struct node *prev;      //pointer to previous node (Closer to front)
    struct node *next;      //pointer to next node (Closer to back)
};

typedef struct node *Nodepointer;

struct queue{
    Nodepointer front;
    Nodepointer back;
};

typedef struct queue *Queuepointer;

main(){
    Queuepointer myqueue;       //create a queue called myqueue
    init(myqueue);              //initialise the queue
    Nodepointer new = (Nodepointer)malloc(sizeof(struct node));
    myqueue->front = new;
}

int init(Queuepointer q){ 
    q = (Queuepointer)malloc(sizeof(struct queue));
    q->front = NULL;
    q->back = NULL;
}
具有以下gdb输出:

Program received signal SIGSEGV, Segmentation fault.
0x08048401 in main () at queue.c:27
27  myqueue->front = new;
知道我做错了什么吗?

init(myqueue);通过值传递指向未分配内存的指针。 因此,init对其不做任何操作(而是在随机位置写入随机内容)

然后,myqueue->stuff再次执行此操作

您应该使用指针对指针

Init将接收队列**,并称为Init(&myqueue)。 在内部,*myqueue=()malloc stuff

另外,我建议您不要使用这些typedef。它们的风格相当糟糕。

调用init时:

int init(Queuepointer q){ 
    q = (Queuepointer)malloc(sizeof(struct queue));
    q->front = NULL;
    q->back = NULL;
}
您将一个指向队列的指针传递到函数中,并初始化该指针在函数中指向(内存中)的位置。通过设置
q=…
,您将为q分配一个新值

不幸的是,调用函数没有看到这一点。您需要将指针传递给指针:

int init(Queuepointer * qp){ 
    Queuepointer q = (Queuepointer)malloc(sizeof(struct queue));
    q->front = NULL;
    q->back = NULL;
    // Set qp:
    *qp = q;
}
然后更改调用函数:

init(&myqueue);
init(&myqueue);

我看到的第一个问题是,“init”函数在“q”中写入分配的指针,这不是您原来的“myqueue”。请记住,C按值传递其参数。一个可能的修正(不是完美的,只是一个提示)是

在“main”中:

myqueue=init()

还要注意,在您的程序中,您没有初始化malloc分配的元素。malloc通常不会清理它分配的内存


关于

您正在按值传递myqueue,因此在init()发生的分配是针对myqueue的副本,而不是myqueue

因此,正确的版本是:

int init(Queuepointer* q){ 
    *q = (Queuepointer)malloc(sizeof(struct queue));
    *q->front = NULL;
    *q->back = NULL;
}
您可以从main调用init()

次要的挑剔,但您的init函数没有返回值,因此可能将其更改为:

void init(Queuepointer *q) {


根据您希望执行错误检查的方式进行调整。

只是一个注释:避免使用关键字“new”。这是C++的保留词,如果你以后用C++程序使用代码,我会遇到一些麻烦。啊,并始终检查malloc是否返回非空值(良好实践)。关于术语的旁注:这里的内容更恰当地称为双链接列表,因为每个节点都有向前和向后指针。在单链表中,每个节点只有一个正向指针。当一个人提到一个链表时,有时最好指定你所说的是哪种链表。皮埃尔,谢谢。。。我相信这是讲师的守则,但出于某种原因我省略了它。Crazyscot,你说得对,我的错。“我以后会记住这一点的,谢谢。@MartinPugh你能展示一下你是如何实现pop()和push()的吗?我也是C语言的新手,我想看看你是怎么做到的。”。非常感谢你。你和帕维尔的回答都很好。我想我现在对代码的理解好多了:)
init(&myqueue);
int init(Queuepointer q){ 
    q = (Queuepointer)malloc(sizeof(struct queue));
    q->front = NULL;
    q->back = NULL;
}
void init(Queuepointer *q) {
int init(Queuepointer * qp){ 
    Queuepointer q = (Queuepointer)malloc(sizeof(struct queue));
    q->front = NULL;
    q->back = NULL;
    *qp = q;
    if(q) {
        return 1;
    } else return 0;
}