2016-09-18 86 views
0

我有一個雙向鏈接列表,我可以從上到下打印,現在我試圖從下向上打印它。反向打印雙向鏈表

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

//defines the struct UserData 
typedef struct 
{ 
    int importance; 
    char taskName[80]; 
}UserData, *UserDataPtr; 

//Defines a node 
typedef struct node { 
    UserData Data; 
    struct node *next; 
    struct node *prev; 
    } Node, *NodePtr; 

NodePtr makeNode(UserData); 

//Declare function printList 
void printList(NodePtr); 

void printListRev(NodePtr); 

int main() 
{ 
    UserData info; 
    NodePtr top, ptr, last, temp; 



    top = NULL; 

    FILE *filein=fopen("Data.txt", "r"); 
    if (filein == NULL) { 
     printf("Error opening file, exiting program.\n"); 
     exit(0); 
    } 

    while(fscanf(filein, "%d%s",&info.importance, info.taskName)==2) 
     { 
      ptr=makeNode(info); 
      if (top == NULL) top = ptr; 
      else last -> next = ptr; 
      last = ptr; 
     }//end while loop 

    printList(top); 


    printListRev(last); 
    }//end Main 


//printList is a function that prints each node as long as it isn't NULL. Once it reaches NULL it terminates, signifying the end of the list. 
void printList(NodePtr ptr) { 
    while (ptr != NULL) { //as long as there's a node 
      printf("%d %s\n", ptr -> Data.importance, ptr -> Data.taskName); 
      ptr = ptr -> next; //go on to the next node 

     } 
    if (ptr == NULL) { 

     printf("Last node data printed moving forward.\n"); 
    } 

    } //end printList 


void printListRev(NodePtr ptr) { 
    while(ptr != NULL){ 
     printf("%d %s\n", ptr -> Data.importance, ptr -> Data.taskName); 
     ptr = ptr -> prev; 


     } 
    }//end printListRev 

//Define function makeNode. Allocates storage for node, stores integer given to it, and returns a pointer to the new node. Also sets next field to NULL 
NodePtr makeNode(UserData info) { 
    NodePtr ptr = (NodePtr) malloc(sizeof (Node)); 
    ptr -> Data = info; 
    ptr -> next = NULL; 
    ptr -> prev = NULL; 
    return ptr; 
} //End makeNode 

這是輸出:

1 task1 
2 task2A 
3 task3A 
2 task2B 
4 task4A 
4 task4B 
3 task3B 
Last node data printed moving forward. 
3 task3B 

而且我不知道爲什麼它不會打印反向的完整列表。反向打印時僅打印一個項目。

直到「最後一個節點數據打印」消息爲止都是正確的。是的,這有點麻煩,我是C新手,我需要清理我的評論等。道歉。

任何人都可以幫忙嗎?

+0

注意點'.'和箭頭' - >'運營商結合非常緊密,決不能與周圍的空間被寫入。 (是的,它在語法上是有效的;你可以把它們放在與結構體/指針和成員名不同的行上,並且它可以被編譯,這是一個普通或常規表達的問題 - C和C++的編寫方式。) –

+2

期間讀階段,你設置'last-> next',但是你從不將任何'prev'成員設置爲NULL以外的任何其他成員。在向前打印列表時,您應該使用'%p'格式打印地址('next'和'prev'成員);你會在'next'值中看到太多的空指針。 –

回答

1

在讀取階段,您設置了last->next,但您從未將任何prev成員設置爲除NULL之外的任何其他成員。

如果您修改printList()代碼以使用%p轉換說明符來打印prevnext成員,則可以看到此內容。

例如:

void printList(NodePtr ptr) 
{ 
    while (ptr != NULL) 
    { 
     printf("%d %s (N = %p, P = %p)\n", ptr->Data.importance, ptr->Data.taskName, 
       (void *)ptr->next, (void *)ptr->prev); 
     ptr = ptr->next; 
    } 
    if (ptr == NULL) 
    { 
     printf("Last node data printed moving forward.\n"); 
    } 
} 

運行時,這將產生(對我來說,在我的Mac):

1 task1 (N = 0x7ff6a94032e0, P = 0x0) 
2 task2A (N = 0x7ff6a9403370, P = 0x0) 
3 task3A (N = 0x7ff6a94033e0, P = 0x0) 
2 task2B (N = 0x7ff6a9403450, P = 0x0) 
4 task4A (N = 0x7ff6a94034c0, P = 0x0) 
4 task4B (N = 0x7ff6a9403530, P = 0x0) 
3 task3B (N = 0x0, P = 0x0) 
Last node data printed moving forward. 
3 task3B 

正如你所看到的,是在相反方向上沒有鏈接,所以打印一個元素後,反向打印停止 - 無論您指向哪個元素。

請注意,當您編寫C時,不得在點.或箭頭->運算符周圍使用空格。它們的綁定非常緊密,不應該使用空格(因爲它在語法上都是合法的)。如果你使用這種非正統的佈局,你的代碼可讀性就會降低。

在掃描碼修復的方法是簡單的:

while (fscanf(filein, "%d%s", &info.importance, info.taskName) == 2) 
    { 
     ptr = makeNode(info); 
     if (top == NULL) 
      top = ptr; 
     else 
      last->next = ptr; 
     ptr->prev = last; 
     last = ptr; 
    } 

我還初始化last = NULL;在循環開始之前;當您使用它來設置以前的指針時,這是至關重要的。您之前可以忽略它,儘管GCC懷抱'我的默認編譯選項可能會使用未初始化'。它實際上並未使用未初始化,但編譯器(GCC 6.2.0)可以理解地關心。

隨着這一變化,輸出爲:

1 task1 (N = 0x7fa4b1602a10, P = 0x0) 
2 task2A (N = 0x7fa4b1602aa0, P = 0x7fa4b16029a0) 
3 task3A (N = 0x7fa4b1602b10, P = 0x7fa4b1602a10) 
2 task2B (N = 0x7fa4b1602b80, P = 0x7fa4b1602aa0) 
4 task4A (N = 0x7fa4b1602bf0, P = 0x7fa4b1602b10) 
4 task4B (N = 0x7fa4b1602c60, P = 0x7fa4b1602b80) 
3 task3B (N = 0x0, P = 0x7fa4b1602bf0) 
Last node data printed moving forward. 
3 task3B 
4 task4B 
4 task4A 
2 task2B 
3 task3A 
2 task2A 
1 task1 

您也可以打印該節點的地址;這將使其更易於跟蹤,每個表指針指向正確的地方:

void printList(NodePtr ptr) 
{ 
    while (ptr != NULL) 
    { 
     printf("%d %s (C = %p, N = %p, P = %p)\n", ptr->Data.importance, ptr->Data.taskName, 
       (void *)ptr, (void *)ptr->next, (void *)ptr->prev); 
     ptr = ptr->next; 
    } 
    printf("Last node data printed moving forward.\n"); 
} 

void printListRev(NodePtr ptr) 
{ 
    while (ptr != NULL) 
    { 
     printf("%d %s (C = %p, N = %p, P = %p)\n", ptr->Data.importance, ptr->Data.taskName, 
       (void *)ptr, (void *)ptr->next, (void *)ptr->prev); 
     ptr = ptr->prev; 
    } 
    printf("Last node data printed moving backward.\n"); 
} 

生產:

1 task1 (C = 0x7fd301c03270, N = 0x7fd301c032e0, P = 0x0) 
2 task2A (C = 0x7fd301c032e0, N = 0x7fd301c03370, P = 0x7fd301c03270) 
3 task3A (C = 0x7fd301c03370, N = 0x7fd301c033e0, P = 0x7fd301c032e0) 
2 task2B (C = 0x7fd301c033e0, N = 0x7fd301c03450, P = 0x7fd301c03370) 
4 task4A (C = 0x7fd301c03450, N = 0x7fd301c034c0, P = 0x7fd301c033e0) 
4 task4B (C = 0x7fd301c034c0, N = 0x7fd301c03530, P = 0x7fd301c03450) 
3 task3B (C = 0x7fd301c03530, N = 0x0, P = 0x7fd301c034c0) 
Last node data printed moving forward. 
3 task3B (C = 0x7fd301c03530, N = 0x0, P = 0x7fd301c034c0) 
4 task4B (C = 0x7fd301c034c0, N = 0x7fd301c03530, P = 0x7fd301c03450) 
4 task4A (C = 0x7fd301c03450, N = 0x7fd301c034c0, P = 0x7fd301c033e0) 
2 task2B (C = 0x7fd301c033e0, N = 0x7fd301c03450, P = 0x7fd301c03370) 
3 task3A (C = 0x7fd301c03370, N = 0x7fd301c033e0, P = 0x7fd301c032e0) 
2 task2A (C = 0x7fd301c032e0, N = 0x7fd301c03370, P = 0x7fd301c03270) 
1 task1 (C = 0x7fd301c03270, N = 0x7fd301c032e0, P = 0x0) 
Last node data printed moving backward. 
+1

您的幫助和詳盡的解釋非常感謝。我選擇這個作爲答案,因爲它的工作原因和你的解釋。我趕緊做了修復,並沒有看到你說什麼初始化最後到NULL,我也得到了一些時髦的輸出結束,但初始化爲NULL時,它的工作完全按照你所描述的。 我希望我能夠獲得足夠的經驗來幫助其他人! –

2

當插入節點進入榜單,你忘了設置prev場到適當的價值。解決方法是簡單的:行ptr = makeNode(info);

順便說後初始化lastNULL,然後設置ptr->prev = last;temp未使用。

+1

完全正確,你的解決方案工作。我給@Jonathan他的解釋的答案,但謝謝你的迴應!非常感謝你,雖然指出了未使用的'temp',我忘了之前想的東西之後將其刪除(笑失敗!) –

+0

其實我沒有注意到它,編譯器做了=)) –

+0

哈哈!來吧,請記住,這一切都很好! –

1

你忘了做鏈接prev

else last -> next = ptr;

應該

else { 
    ptr->prev = last; 
    last -> next = ptr; 
} 
+0

'最後'初始化不是必需的。 (雖然這是一個好習慣) – BLUEPIXY