我有一个双向链表,我可以从上到下打印,现在我正在尝试从下到上打印它。
#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 :(得分:2)
将节点插入列表时,您忘记将prev
字段设置为适当的值。修复很简单:将last
初始化为NULL
,然后在ptr->prev = last;
行
ptr = makeNode(info);
顺便说一下,temp
未使用。
答案 1 :(得分:1)
在阅读阶段,您设置last->next
,但您从未将prev
成员设置为NULL
以外的任何其他成员。
如果您修改printList()
代码以使用prev
转换说明符打印next
和%p
成员,则可以看到此内容。
例如:
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抱怨可能会使用未初始化的&#39;使用我的默认编译选项。它实际上并没有被初始化,但编译器(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.
答案 2 :(得分:1)
您忘记链接到prev
。
else last -> next = ptr;
应该是
else {
ptr->prev = last;
last -> next = ptr;
}