2010-03-21 40 views
2

我负责在C中创建一个队列数据结构作为链表。我们的讲师给了我们大量的代码来实现一个堆栈,但我们必须调整它来创建一个队列。我们的讲师给我们的代码最终不会像我为队列写的代码那样完全编译和分段。我对结构,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; 
} 

的想法是,队列结构“包含”在队列中的第一和最后一个节点,并创建一个节点时,myQueue中被更新。但是,我甚至无法达到那个部分(流行和推动都是书面的,但为了简洁省略)。该代码是在段错误行

myqueue->front = new; 

用以下GDB输出:

Program received signal SIGSEGV, Segmentation fault. 
0x08048401 in main() at queue.c:27 
27 myqueue->front = new; 

任何想法,我做错了吗?

+0

只是一个评论:避免使用关键字'新'。这是C++的一个保留字,如果稍后使用C++程序使用代码,会遇到一些麻烦。啊,并且总是检查malloc返回一个非NULL值(最佳做法)。 – Pierre 2010-03-21 20:19:26

+0

关于术语的一个注意事项:这里所说的更适当地称为*双链表*,因为每个节点都有向前和向后指针。在*单链接列表中,每个节点只有一个转发指针。当一个人谈到一个*链表时*有时是一个好主意,指定你在谈论哪种。 – crazyscot 2010-03-21 20:30:44

+0

皮埃尔,谢谢......我相信那是在讲师的代码中,但是我由于某种原因省略了它。 Crazyscot,你是对的,我的坏。今后会记住这一点,谢谢。 – 2010-03-21 20:32:57

回答

5

当你调用初始化:

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); 
+0

非常感谢。你和帕维尔的答案都非常好。我认为我现在更了解代码:) – 2010-03-21 20:27:48

3

init(myqueue);按值传递未分配内存的指针。因此,init不会做任何事情,因此(而是随机地写随机事物)。

然后,myqueue-> stuff再次。

您应该使用指针指针。

初始化将接收队列**,并调用init(& myqueue)。 Inside,* myqueue =()malloc stuff

此外,我建议你对这些typedefs。他们的风格相当糟糕。

2

我看到的第一个问题是“初始化”功能的“Q写入分配指针“,那不是你原来的”myqueue“。请记住C按值传递它的参数。一种可能的校正(不完美的,只是一个提示)是

Queuepointer init(void) 
    Queuepointer q; 
    q = (Queuepointer)malloc(sizeof(struct queue)); 
    q->front = NULL; 
    q->back = NULL; 
    return q; 
} 
` 

而在 “主”:

myQueue中=的init();

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

问候

0

你传入myQueue中的值,因此分配发生在的init()是myQueue中的副本不myQueue中。

所以正确的版本是:

int init(Queuepointer* q){ 
    *q = (Queuepointer)malloc(sizeof(struct queue)); 
    *q->front = NULL; 
    *q->back = NULL; 
} 

,你可以从主

init(&myqueue); 
0
int init(Queuepointer q){ 
    q = (Queuepointer)malloc(sizeof(struct queue)); 
    q->front = NULL; 
    q->back = NULL; 
} 

小鸡蛋里挑骨头调用的init(),但你的初始化函数没有返回值,所以可能变化它到:

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

根据您希望如何执行错误检查进行调整。