2010-03-21 41 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; 
} 

根據您希望如何執行錯誤檢查進行調整。