C 反向打印双链接列表
我有一个可以从上到下打印的双链接列表,现在我正尝试从下到上打印它C 反向打印双链接列表,c,C,我有一个可以从上到下打印的双链接列表,现在我正尝试从下到上打印它 #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 typede
#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
我也不知道为什么它不会反向打印完整的列表。反向打印时只打印一个项目
直到“最后一个节点数据打印”消息正确为止。是的,这有点混乱,我是C新手,我需要整理我的评论等等。抱歉
有人能帮忙吗?在读取阶段,您设置了
last->next
,但从未将任何prev
成员设置为除NULL
之外的任何值
如果使用%p
转换说明符修改printList()
代码以打印prev
和next
成员,则可以看到这一点
例如:
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上):
正如您所看到的,没有反向链接,因此在打印一个元素(无论您指向哪个元素)后,反向打印停止
请注意,在编写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抱怨我的默认编译选项“可能未初始化使用”。它实际上并不是在未初始化的情况下使用的,但编译器(GCC6.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.
在读取阶段,您设置了last->next
,但从未将任何prev
成员设置为NULL
以外的任何值
如果使用%p
转换说明符修改printList()
代码以打印prev
和next
成员,则可以看到这一点
例如:
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上):
正如您所看到的,没有反向链接,因此在打印一个元素(无论您指向哪个元素)后,反向打印停止
请注意,在编写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抱怨我的默认编译选项“可能未初始化使用”。它实际上并不是在未初始化的情况下使用的,但编译器(GCC6.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.
将节点插入列表时,您忘记将prev
字段设置为适当的值。修复很简单:将last
初始化为NULL
,然后设置ptr->prev=last代码>行后ptr=makeNode(info)代码>
顺便说一下,temp
未使用。在列表中插入节点时,您忘记将prev
字段设置为适当的值。修复很简单:将last
初始化为NULL
,然后设置ptr->prev=last代码>行后ptr=makeNode(info)代码>
顺便说一下,temp
是未使用的。您忘了链接到prev
else last->next=ptr代码>
应该是
else {
ptr->prev = last;
last -> next = ptr;
}
你忘了链接到prev
else last->next=ptr代码>
应该是
else {
ptr->prev = last;
last -> next = ptr;
}
请注意,点
和箭头->
运算符绑定非常紧密,不应使用空格进行书写。(是的,它在语法上是有效的;可以将它们放在与结构/指针和成员名分开的一行上,并且编译它。这是一个正常或常规的演示问题——C和C++的编写方式)。您将last->next
设置为空,但从未将任何prev
成员设置为空。在向前打印列表时,应使用%p
格式打印地址(下一个和上一个成员);您将在下一个值中看到太多的空指针。请注意,点
和箭头->
运算符绑定非常紧密,不应使用空格进行书写。(是的,它在语法上是有效的;可以将它们放在与结构/指针和成员名分开的一行上,并且编译它。这是一个正常或常规的演示问题——C和C++的编写方式)。您将last->next
设置为空,但从未将任何prev
成员设置为空。在向前打印列表时,应使用%p
格式打印地址(下一个和上一个成员);您将在next
值中看到太多的空指针。非常感谢您的帮助和详细的解释。我选择这个作为答案,因为它有效,也因为你的解释。我急忙去做修复,没有看到你最后一次说的初始化